За последние 24 часа нас посетили 231590 программистов и 1779 роботов. Сейчас ищут 3009 программистов ...

Оптимизация SQL запроса

Тема в разделе "MySQL", создана пользователем vayas, 17 дек 2012.

  1. vayas

    vayas Активный пользователь

    С нами с:
    13 дек 2012
    Сообщения:
    167
    Симпатии:
    9
    Адрес:
    Пермь
    SQL запрос выполняется слишком долго как его можно оптимизировать
    Код (Text):
    1.  
    2. SELECT concat(country.name, ', ', region.name, ', ', city.name, ', ', raion.name) AS temp
    3. FROM mlt_adr_country country
    4. LEFT JOIN mlt_adr_city city ON country.id = city.country_id
    5. LEFT JOIN mlt_adr_region region ON city.region_id = region.id
    6. LEFT JOIN mlt_adr_raion raion ON city.raion_id = raion.id
    7. WHERE CASE
    8. WHEN (SELECT * FROM (SELECT count(name) FROM mlt_adr_country WHERE name LIKE 'Россия%') as tem) > 0 THEN country.name LIKE 'Россия%'
    9. WHEN (SELECT * FROM (SELECT count(name) FROM mlt_adr_city WHERE name LIKE 'Теплу%') as tem) > 0 THEN city.name LIKE 'Теплу%'
    10.        
    11. END
    12. GROUP BY city.id
    Сейчас он выполняется 30 сек всего 200к записей
    Условий будет таких же ещё штук пять Т.е. примерно запрос будет около минуты выполняться.
    Как возможно его переделать
     
  2. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    Вот от этого надо избавиться
    WHEN (SELECT * FROM (SELECT count(name) FROM mlt_adr_country WHERE name LIKE 'Россия%') as tem) > 0 THEN
    WHEN (SELECT * FROM (SELECT count(name) FROM mlt_adr_city WHERE name LIKE 'Теплу%') as tem) > 0 THEN

    Добавлено спустя 1 минуту 1 секунду:
    т.к. эти запросы у вас постоянные, то сделайте их перед большим запросом и подставляйте результат.
     
  3. vayas

    vayas Активный пользователь

    С нами с:
    13 дек 2012
    Сообщения:
    167
    Симпатии:
    9
    Адрес:
    Пермь
    Вообще в целом идея такая, что бы сделать поиск с автозаполнением как на google maps.
    Именно по регионам городам странам.
    Что бы например в одно и то же поле можно было написать москва или московская область или например москва ленинградское шоссе ну и соответственно он максимально близко понимал текст который впишет пользователь и вывел наиболее подходящие записи.
     
  4. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    ты прочёл, что я написал? о_О
     
  5. vayas

    vayas Активный пользователь

    С нами с:
    13 дек 2012
    Сообщения:
    167
    Симпатии:
    9
    Адрес:
    Пермь
    Да ) прочел, я подумал на счет этого следующим образом, почему бы это не разделить.
    Отдельно выполнить запрос, И если он нам вернет хоть одну строку, то тогда подставляем определенный параметр в более тяжелый запрос.
    Но тогда маленьких запросов может быть гораздо больше.
    И при одном поисковом запросе выполнять пять лишних.......

    Добавлено спустя 3 минуты 21 секунду:
    Кстати ещё если просто выполнить
    Код (Text):
    1.  
    2. SELECT concat(country.name, ', ', region.name, ', ', city.name, ', ', raion.name) AS temp
    3. FROM mlt_adr_country country
    4. LEFT JOIN mlt_adr_city city ON country.id = city.country_id
    5. LEFT JOIN mlt_adr_region region ON city.region_id = region.id
    6. LEFT JOIN mlt_adr_raion raion ON city.raion_id = raion.id
    7. WHERE country.name LIKE 'Р%'
    8. GROUP BY city.id
    И этот запрос выполняется 30 секунд И почему то если сделать LIMIT 5, то выполняется столько же, ну чуть чуть меньше на несколько мили секунд.
     
  6. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    надо выбрать те, кого вам надо, потом заюзать конструкцию типа WHERE `id` IN (1,2,3,4,...)

    если надо ещё что-то, то добавлять поля с предварительно просчитанными данными. Например " concat(country.name, ', ', region.name, ', ', city.name, ', ', raion.name) AS temp " хорошо бы вкрячить в виде поля в какую-нить таблицу. Это будет некоторым кешем, позволяющим индексацию, и соотв ускорение всего этого дела.
     
  7. vayas

    vayas Активный пользователь

    С нами с:
    13 дек 2012
    Сообщения:
    167
    Симпатии:
    9
    Адрес:
    Пермь
    Мы не как не выберем поле то одно. И соответственно нужно исходить из одного поля
    Вот пример на google maps там же поле одно, не ужели оно все из одной таблицы берет...

    Добавлено спустя 5 минут 9 секунд:
    Убрал GROUP BY и добавил LIMIT 5 запрос выполняется 0,100 сек,
    Но почему используя GROUP BY он так тормозит да же если добавить LIMIT 5 процесс не сильно то изменяется
     
  8. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    если учесть все правила "не и ни" и запятые, то я всё равно не понял смысл фразы.

    Добавлено спустя 1 минуту 41 секунду:
    потому что сначала делается выборка, потом уже групбай, а потом сортировка, потом лимит =)

    попробуй LIMIT 100000, 5. Сначала построится 100005 таблица, потом всё остальное :D
     
  9. vayas

    vayas Активный пользователь

    С нами с:
    13 дек 2012
    Сообщения:
    167
    Симпатии:
    9
    Адрес:
    Пермь
    Возможно я не правильно понял смысл нижней фразы
    И вот как я выберу тех кого мне надо? Если например кто то захочет написать "РОССИЯ", а кто то "КИРОВ ул МИРА"
    И в качестве автозаполнения должно будет предложено максимально похожий вариант
     
  10. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.408
    Симпатии:
    1.768
    WHEN (SELECT * FROM (SELECT count(name) FROM mlt_adr_country WHERE name LIKE 'Россия%') as tem) > 0 THEN
    WHEN (SELECT * FROM (SELECT count(name) FROM mlt_adr_city WHERE name LIKE 'Теплу%') as tem) > 0 THEN

    сделай эти выборки ПЕРЕД большим запросом, а в него вставь уже результат.
    Иначе ты делаешь эти выборки на каждую строку каждый раз *каждый раз * на второй позапрос каждый раз * каждый раз...
     
  11. vayas

    vayas Активный пользователь

    С нами с:
    13 дек 2012
    Сообщения:
    167
    Симпатии:
    9
    Адрес:
    Пермь
    )))) Дошло до меня наконец то. Я понял что ты имеешь ввиду теперь, спасибо igordata
     
  12. sobachnik

    sobachnik Старожил

    С нами с:
    20 апр 2007
    Сообщения:
    3.380
    Симпатии:
    13
    Адрес:
    Дмитров, МО
    Самый быстрый вариант - для автозаполнения создай вообще отдельную таблицу. Одну. В ней (в одной колонке) перечисли все тексты, которые имеются в базе, по которым может быть поиск. А лучше даже пихай туда не все, а только наиболее вероятные к поиску. Мелкие деревеньки сибири - можешь туда не писать, только города.

    Добавлено спустя 1 минуту 32 секунды:
    При добавлении/редактировании записей в таблицах country/region/raion/city - автоматически также добавляй/редактируй записи в этой дополнительной таблице.

    Добавлено спустя 6 минут 22 секунды:
    Тогда поиск будет простым
    Код (Text):
    1. SELECT * FROM `autocomplete_table` WHERE `text_field` LIKE '%search_text%';
     
  13. Chushkin

    Chushkin Активный пользователь

    С нами с:
    17 дек 2010
    Сообщения:
    1.062
    Симпатии:
    91
    Адрес:
    Мещёра, Центр, Болото N3
    И медленным, ибо никаких индексов.

    Более правильным, по моему мнению, будет простая табличка, где хранятся варианты запросов юзера, и полнотекстовый поиск (с индексированием, естественно) - будет работать быстро, даже без кеширования (сотые доли секунды).
     
  14. vayas

    vayas Активный пользователь

    С нами с:
    13 дек 2012
    Сообщения:
    167
    Симпатии:
    9
    Адрес:
    Пермь
    У меня на счет этого то же есть мысли, только вот правда не знаю в плане скорости как это дело будет.
    Вот тут я не совсем понимаю, можно по подробнее, как я соберу варианты запросов Юзера?