我有一个sql查询,需要连接5个表。到目前为止我已经尝试过这个查询。 它正在工作,但需要很长时间。这里可以做什么来优化以下查询?
$select_query = 'select ';
$select_query .= "ROUND((
6371 * ACOS(
COS(RADIANS('.$lat.')) COS(RADIANS(lat)) COS(
RADIANS(lng) - RADIANS('.$lng.')
) + SIN(RADIANS('.$lat.')) * SIN(RADIANS(lat))
)
),2) AS property_distance ,";
$select_query .= "
pro.id as id,
pro.user_id,
pro.category_id,
pro.total_price,
pro.size,
pro.lat,
pro.lng,
pro.city,
pro.city_english,
pro.created_at,
pimg.image as property_images,
pimg.property_id,
pa.property_id,
pa.category_attribute_id,
pa.is_multiple_data,
pa.attribute_value,
ca.category_id,
ca.attribute_name,
ct.category_id,
ct.category_name,
cat.attribute_id,
cat.attribute_label,
cat.locale
FROM
property pro FORCE INDEX (property_index)
left join property_images pimg on pro.id=pimg.property_id
JOIN property_attributes pa ON
pa.property_id = pro.id
left JOIN category_attributes ca ON
ca.id = pa.category_attribute_id
left JOIN category_attributes_translations cat ON
ca.id = cat.attribute_id
left JOIN categories_translation ct ON
pro.category_id = ct.category_id
WHERE pro.is_confirm='1' and pro.status='1' and pro.deal_finish='0' and cat.locale='" . $locale . "' and ct.locale='" . $locale . "'
GROUP BY pro.id HAVING property_distance<=10 ORDER by pro.id DESC";
然后最后运行这个查询。
请建议我优化此查询的正确方法。
最佳答案
在进行任何连接之前,我会修改查询以遍历属性表并消除尽可能多的行。 HAVING 子句中关于大圆距离计算结果的条件将要求对 WHERE 子句未消除的每一行进行计算。
我会只针对 property
编写一个查询表,类似这样的:
SELECT ROUND( ( 6371 * ACOS( COS(RADIANS( :lat ) )
* COS(RADIANS(pro.lat))
* COS(RADIANS(pro.lng) - RADIANS( :lng ) )
+ SIN(RADIANS( :lat ))
* SIN(RADIANS(pro.lat))
)
)
,2) AS property_distance
, pro.id
, pro.user_id
, pro.category_id
, pro.total_price
, pro.size
, pro.lat
, pro.lng
, pro.city
, pro.city_english
, pro.created_at
FROM property pro
WHERE pro.is_confirm = '1'
AND pro.status = '1'
AND pro.deal_finish = '0'
HAVING property_distance <= 10
ORDER
BY pro.id DESC
这假设 id
是唯一的property
table 。这应该能够有效利用具有前导列的索引 deal_finish
, status
和is_confirm
以消除某些行的考虑。
... ON property (deal_finish,status,is_confirm,...)
一旦我们有了这个集合,我们就可以在外部查询中将其引用为内联 View (派生表),并且外部查询可以与其他表进行联接。
请注意,如果 product_images
中有多个匹配行并在 product_attributes
,对两个表进行联接将创建一个半笛卡尔积,每一行都来自 product_image
与 product_attribute
中的每一行匹配。即 product_image
中的 20 行交叉连接到 product_attribute
中的 20 行将生成一组 400 行。
SELECT c.*
FROM ( -- inline view query
SELECT ROUND( ( 6371 * ACOS( COS(RADIANS( :lat ) )
* COS(RADIANS(pro.lat))
* COS(RADIANS(pro.lng) - RADIANS( :lng ) )
+ SIN(RADIANS( :lat ))
* SIN(RADIANS(pro.lat))
)
)
,2) AS property_distance
, pro.id
, pro.user_id
, pro.category_id
, pro.total_price
, pro.size
, pro.lat
, pro.lng
, pro.city
, pro.city_english
, pro.created_at
FROM property pro
WHERE pro.is_confirm = '1'
AND pro.status = '1'
AND pro.deal_finish = '0'
HAVING property_distance <= 10
ORDER BY pro.id DESC
) c
LEFT
JOIN product_images pimg
ON pimg.product_id = c.id
ORDER BY c.id DESC
现在出现了使用 GROUP BY
的整个问题。折叠行以及功能上不依赖的表达式、ONLY_FULL_GROUP_BY sql_mode 等行为。
关于mysql - 在mysql中使用多个连接时加快查询速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57420339/