Как использовать индексирование для объединения нескольких таблиц в одном запросе? - PullRequest
0 голосов
/ 04 мая 2019

Запрос с несколькими объединениями таблиц занимает слишком много времени.Как выполнить индексацию для запроса ниже:

ЗАПРОС:

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 минуте.

Может ли кто-нибудь помочь мне применить индексацию к этому запросу?

1 Ответ

0 голосов
/ 06 мая 2019

Было бы полезно иметь 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

Поскольку в предложении WHERE есть условие FULLTEXT, он, вероятно, сначала это сделает. Однако, если в этих областях тысячи строк, нам нужно копать дальше.

rai.rating <= '' кажется очень странным; что вы ожидаете от "<= ''"? </p>

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: многие и т. Д. Затем GROUP BY пытается вернуться только к одной строке на идентификатор. Если бы не вся фильтрация, есть обходные пути.

Между тем, 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 таблиц, каждая из которых снабжена "идентификатором ресторана"? (Могут быть веские причины, но это выглядит подозрительно.) Они 1: 1 или 1: много?

...