Я использую класс WP_GeoQuery, который расширяет WP_Query, чтобы мы могли искать сообщения по британскому почтовому индексу (лат и длинные координаты). Он работает очень хорошо, но он невероятно медленный.Как ускорить поиск GEO в WordPress
Есть ли какие-либо шаги, которые я могу предпринять при расширении WP_Query с помощью приведенного ниже кода, чтобы ускорить запросы MySQL?
class WP_GeoQuery extends WP_Query
{
private $_search_latitude = NULL;
private $_search_longitude = NULL;
private $_radius = NULL;
/**
* Constructor - adds necessary filters to extend Query hooks
*/
public function __construct($args = array())
{
// Extract Latitude
if(!empty($args['latitude'])) { $this->_search_latitude = $args['latitude']; }
// Extract Longitude
if(!empty($args['longitude'])) { $this->_search_longitude = $args['longitude']; }
// Extract Longitude
if(!empty($args['radius'])) { $this->_radius = $args['radius']; }
// unset lat/long
unset($args['latitude'], $args['longitude'], $args['radius']);
// Extract Post type
if(!empty($args['post_type'])) { $this->_post_type = $args['post_type']; }
add_filter('posts_fields', array($this, 'posts_fields'), 10, 2);
add_filter('posts_join', array($this, 'posts_join'), 10, 2);
add_filter('posts_where', array($this, 'posts_where'), 10, 2);
add_filter('posts_orderby', array($this, 'posts_orderby'), 10, 2);
add_filter('posts_distinct', array($this, 'posts_distinct'), 10, 2);
// Run query
parent::query($args);
// Remove filters so only WP_GeoQuery queries this way
remove_filter('posts_fields', array($this, 'posts_fields'));
remove_filter('posts_join', array($this, 'posts_join'));
remove_filter('posts_where', array($this, 'posts_where'));
remove_filter('posts_orderby', array($this, 'posts_orderby'));
remove_filter('posts_distinct', array($this, 'posts_distinct'));
} // END public function __construct($args = array())
/**
* Return only distinct results
*/
function posts_distinct()
{
return "DISTINCT";
} // END public function posts_distinct()
/**
* Selects the distance from a haversine formula
*/
public function posts_fields($fields)
{
global $wpdb;
if(!empty($this->_search_latitude) && !empty($this->_search_longitude))
{
$fields .= sprintf(", (3959 * acos(
cos(radians(%s)) *
cos(radians(latitude.meta_value)) *
cos(radians(longitude.meta_value) - radians(%s)) +
sin(radians(%s)) *
sin(radians(latitude.meta_value))
)) AS distance ", $this->_search_latitude, $this->_search_longitude, $this->_search_latitude);
}
$fields .= ", latitude.meta_value AS latitude ";
$fields .= ", longitude.meta_value AS longitude ";
$fields .= ", location.meta_value AS location ";
return $fields;
} // END public function posts_join($join, $query)
/**
* Makes joins as necessary in order to select lat/long metadata
*/
public function posts_join($join, $query)
{
global $wpdb;
$join .= " INNER JOIN {$wpdb->postmeta} AS latitude ON {$wpdb->posts}.ID = latitude.post_id ";
$join .= " INNER JOIN {$wpdb->postmeta} AS longitude ON {$wpdb->posts}.ID = longitude.post_id ";
$join .= " INNER JOIN {$wpdb->postmeta} AS location ON {$wpdb->posts}.ID = location.post_id ";
return $join;
} // END public function posts_join($join, $query)
/**
* Adds where clauses to compliment joins
*/
public function posts_where($where)
{
$where .= ' AND latitude.meta_key="postcode_lat" ';
$where .= ' AND longitude.meta_key="postcode_lng" ';
$where .= ' AND location.meta_key="individual_details_postcode" ';
if(!empty($this->_search_latitude) && !empty($this->_search_longitude) && !empty($this->_radius))
{
if(is_numeric($this->_radius))
{
$where .= sprintf(' HAVING distance <= %s ', $this->_radius);
}
}
return $where;
} // END public function posts_where($where)
/**
* Adds where clauses to compliment joins
*/
public function posts_orderby($orderby)
{
if(!empty($this->_search_latitude) && !empty($this->_search_longitude))
{
$orderby = " distance ASC, " . $orderby;
}
return $orderby;
} // END public function posts_orderby($orderby)
}
Сколько сообщений имеет значения lat/long в post_meta в вашей WP-установке? Десятки? Сотни? Десятки тысяч? –
Только две должности в данный момент. Это в настоящее время находится на этапах тестирования. Несмотря на то, что я хорошо разбираюсь в WordPress, мне не хватает знаний в оптимизации MySQl, и я предполагаю, что скорость этого запроса имеет проблемы. По умолчанию поиск по WordPress происходит очень быстро, но как только я использую этот класс, который изменяет WP_Query, загрузка занимает 1 минуту, хотя есть только две записи для запроса. – Steven
Я думал о вашей проблеме. Очень странно, что запрос только для двух лат/длинных точек занимает так много времени. Интересно, можете ли вы получить доступ к экземпляру MySQL с помощью phpmyadmin или какого-либо другого клиента MySQL * во время выполнения запроса, * получить текст запроса с помощью 'SHOW FULL PROCESSLIST' и опубликовать текст запроса здесь. –