具有多个表联接的查询花费太多时间。如何为以下查询建立索引:
查询:
select ri.id, LOWER(REPLACE(ri.name,' ','-')) as urlName,ri.name,
ri.logo,
group_concat(distinct rc.cuisine order by rc.cuisine asc SEPARATOR ',
'
) as 'cuisine_string', rc.cuisine, rai.rating, rai.min_order_amount,
rai.latitude, rai.longitude, rai.delivery_time, rdf.start_dist,
rdf.end_dist, rdf.fee, ri.address_search, rai.delivery_facility,
ri.status as 'restaurant_status', rt.day, rt.status 'opening_status',
rt.opening_time, rt.closing_time,
' - ',rdf.end_dist,
' km',' : ','₹',fee) SEPARATOR '~') as 'delivery_fee_string',
GROUP_CONCAT(distinct CONCAT(rdf.start_dist, ( SELECT MATCH (ri.address_search) AGAINST ('Kahilipara,
Guwahati, Assam, India') as relevance
from restaurant_info ri
where ri.id = rai.restaurant_id
and ri.id = rt.restaurant_id
and ri.id = rdf.restaurant_id
and ri.id = rc.restaurant_id) as ord , ( 3959 * acos ( cos ( radians(26.1428694) ) * cos( radians( rai.latitude ) ) * cos( radians( rai.longitude ) - radians(91.768487) ) + sin ( radians(26.1428694) ) * sin( radians( rai.latitude ) ) ) ) AS distance
from restaurant_info ri
inner join restaurant_additional_info rai ON ri.id = rai.restaurant_id
inner join restaurant_timing rt ON ri.id = rt.restaurant_id
inner join restaurant_delivery_fee rdf ON ri.id = rdf.restaurant_id
inner join restaurant_cuisine rc ON ri.id = rc.restaurant_id
where ri.status = 1
and rt.status = 1
and rt.day = lower(DATE_FORMAT(NOW(),'%a'))
and rai.delivery_facility != 1
and rai.min_order_amount <= 100
and rai.rating <= ''
and MATCH (ri.address_search) AGAINST ('Kahilipara, Guwahati,
Assam, India'
)
and rt.opening_time < '12:40:21'
and rt.closing_time > '12:40:21'
group by ri.id
having rdf.start_dist = 0
and distance < 3.10686
order by distance asc
LIMIT 100 OFFSET 0
问题描述-此查询需要8.5秒的时间才能运行。我的应用程序包含1-2个这样的查询。因此在服务器上的加载时间接近1分钟。
有人可以帮助我对此查询应用索引编制吗?
答案 0 :(得分:0)
为各个表使用SHOW CREATE TABLE
会有所帮助。另外,EXPLAIN SELECT ...
。
where ri.status = 1
and rt.status = 1
and rt.day = lower(DATE_FORMAT(NOW(),'%a'))
and rai.delivery_facility != 1
and rai.min_order_amount <= 100
and rai.rating <= ''
and MATCH (ri.address_search) AGAINST ('Kahilipara, Guwahati, Assam, India')
and rt.opening_time < '12:40:21'
and rt.closing_time > '12:40:21'
group by ri.id
having rdf.start_dist = 0
and distance < 3.10686
order by distance asc
LIMIT 100 OFFSET 0
由于FULLTEXT
子句中有一个WHERE
条件,因此它可能会首先这样做。但是,如果这些区域中有成千上万的行,我们需要进一步挖掘。
rai.rating <= ''
似乎很奇怪;您对“ <=”有什么期望?
having rdf.start_dist = 0
-似乎属于WHERE
子句,而不是HAVING
子句。
一个大问题是您的范围测试分散在多个表中:
rt -- just a certain day of the week
rai -- limited amount, etc
ri -- certain regions
rt -- time range, complicated by using 2 columns
即使这些字段位于同一表中,计算起来仍然会很昂贵。
distance < ...
-可以通过链接中讨论的“边界框”进行优化,但是由于其他问题,它没有太大帮助。
JOIN ... GROUP BY id
-这可能是“爆炸爆炸”的情况。发生的情况是JOINs
通过加入1:many等扩展了正在查看的“行”的数量。然后GROUP BY
试图返回每个id仅一行。如果不是所有筛选都可以,则有解决方法。
与此同时,GROUP BY
可能未正确使用。参见ONLY_FULL_GROUP_BY
。
order by distance LIMIT ..
-强制查询收集所有行(数千?),然后进行排序并提供最多100行。
rt.day = lower(DATE_FORMAT(NOW(),'%a'))
-使用适当的排序规则,您不需要LOWER()
。
MATCH (ri.address_search) ..
和distance < ..
似乎多余。
为什么有5个表格,每个表格都以“餐厅ID”作为关键字? (可能有正当的理由,但看起来有些可疑。)它们是1:1还是1:很多?