|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Добрый день! Подскажите, какой индекс лучше создать в базе данных(6000000 млн.записей) для максимальной работы SQL запроса со следующим условием отбора: SELECT...WHERE VAL(Kod) IN(SELECT Kod FROM Zapros) AND Rik IN(2010,2011) AND Ozn IN(1,101) ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2011, 15:15 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
6000000 млн.записей или все-таки 6 млн.записей? мало инфы указал. Сколько записей под каждое подусловие попадает? Rik IN(2010,2011) Ozn IN(1,101) VAL(Kod) IN(SELECT Kod FROM Zapros) Сколько всего записей в результате запроса получается? подозреваю что надо индекс по KOD, только запрос надо немного переделать чтобы индекс заработал. VAL() убрать как-то так: Код: plaintext 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2011, 17:19 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Dima T6000000 млн.записей или все-таки 6 млн.записей? мало инфы указал. Сколько записей под каждое подусловие попадает? Rik IN(2010,2011) Ozn IN(1,101) VAL(Kod) IN(SELECT Kod FROM Zapros) Сколько всего записей в результате запроса получается? подозреваю что надо индекс по KOD, только запрос надо немного переделать чтобы индекс заработал. VAL() убрать как-то так: Код: plaintext 1.
Да, записей 6 млн. Количество Kod в базе Zapros может быть до 20 записей, а результат выборки по Rik и Ozn для каждого Kod, может быть до 1000 записей. Индекс по KOD есть, убрал VAL(), как Вы и советовали, но, скорость от этого практически не поменялась(обработка идёт около 1 мин.). ... |
|||
:
Нравится:
Не нравится:
|
|||
02.12.2011, 19:40 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
sys(3054, 2) - выводит как работает оптимизатор. Посмотри какие индексы он берет. Провел тест: оптимизируется Rik IN(2010,2011), т.е. для такого условия индекс по Rik он задействует это НЕ оптимизируется Kod IN (SELECT ..), т.е. будет перебор результата выборки по остальным условиям. Вобщем для задействования индекса по Kod надо заменять подзапрос на макроподстановку: генеришь список значений из Zapros в переменную lcZapros и Код: plaintext 1.
Тут возможна проблема с длинной запроса в символах, если будут ошибки что запрос слишком длинный, то разбивать на несколько запросов, а потом склеивать результаты. По выбору индексов ты не сказал что я просил. Сделай такие запросы: Код: plaintext 1. 2. 3.
если запрос возвращает много записей, то индекс по этому полю будет бесполезен. Сколько значит "много" точно не скажу, думаю 20-25% от размера исходной таблицы. Если получишь более 50% то такой индекс может даже замедлять запрос. Чем меньше записей выбирается по конкретному условию для поля тем больший эффект даст индекс по этому полю. И условия надо расположить по мере убывания эффективности индекса, т.е. например если Ozn IN (1,101) дает наименьшее количество, то его поставить вперед: Код: plaintext 1.
... |
|||
:
Нравится:
Не нравится:
|
|||
03.12.2011, 09:40 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Макс_П, 1-ДФ? ;) ... |
|||
:
Нравится:
Не нравится:
|
|||
04.12.2011, 16:02 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Макс_ПДобрый день! Подскажите, какой индекс лучше создать в базе данных(6000000 млн.записей) для максимальной работы SQL запроса со следующим условием отбора: SELECT...WHERE VAL(Kod) IN(SELECT Kod FROM Zapros) AND Rik IN(2010,2011) AND Ozn IN(1,101) Код: plaintext 1. 2. 3.
Да, неплохо бы увидеть ВЕСЬ селект. Ибо вместо звездочки невесть что стоять может.... ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2011, 11:33 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Код: plaintext 1.
Спасибо! Очень помог совет. Теперь программа выполняется за 2 секунды. И, в догонку, ещё вопрос - Есть две таблицы - Т1 и Т2. В таблице Т1 поля а1,а2,...,а20, в таблице Т2 поля а1,а2,...,а5. Как КРАСИВО и с оптимизацией оставить в базе Т1 только те записи, которых нет в Т2 (интересуют только поля а1-а5)? Структура полей абсолютно одинаковая. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2011, 17:13 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Dima Tsys(3054, 2) - выводит как работает оптимизатор. Посмотри какие индексы он берет. Провел тест: оптимизируется Rik IN(2010,2011), т.е. для такого условия индекс по Rik он задействует это НЕ оптимизируется Kod IN (SELECT ..), т.е. будет перебор результата выборки по остальным условиям. Ты не туда смотрел. В данном случае надо "ловить" оптимизацию Join, а не Where. Т.е. нужно sys(3054,12). Оптимизатор показывает, что промежуточный результат объединения использует индекс в подзапросе. Другими словами, нужен индекс по тому полю, которое отбирается в позапросе. Для конструкции Код: plaintext 1.
Нужен индекс по полю Код в таблице Zapros. Впрочем, оптимизатор не раскрывает использует ли он индекс по полю другой таблицы при формировании промежуточного результата объединения. Теоретически, должен был бы. Но как оно на самом деле - не известно. PS: Как мне кажется, SYS(3054,1) и SYS(3054,2) оставлены для совместимости. Всегда для надежности надо ставить 11 или 12. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.12.2011, 20:36 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
ВладимирМDima Tsys(3054, 2) - выводит как работает оптимизатор. Посмотри какие индексы он берет. Провел тест: оптимизируется Rik IN(2010,2011), т.е. для такого условия индекс по Rik он задействует это НЕ оптимизируется Kod IN (SELECT ..), т.е. будет перебор результата выборки по остальным условиям. Ты не туда смотрел. В данном случае надо "ловить" оптимизацию Join, а не Where. Т.е. нужно sys(3054,12). Оптимизатор показывает, что промежуточный результат объединения использует индекс в подзапросе. Другими словами, нужен индекс по тому полю, которое отбирается в позапросе. Я туда и не смотрел, не люблю sys(3054), загаживает экран всякими буковками :) Тут главный тормоз в том что по сетке качается много лишних записей. Это проще всего смотреть диспетчером задач - добавляем колонку "Скачано, байт" и смотрим чего дает каждый вариант. Только для чистоты эксперимента фокс лучше перезапускать перед каждым запросом, чтобы влияние кэша фокса исключить. Посмотрел с sys(3054,11) и sys(3054,12) - не использует оптимизатор индекс для подзапроса. А вот переделывание в JOIN дало результат аналогичный выше предложенной макроподстановке. Чего-то не догадался его попробовать в прошлый раз. Макс_П попробуй такой вариант: Код: plaintext 1.
если скорость нормальная будет - лучше его используй чем макроподстановки. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 07:44 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Макс_ПЕсть две таблицы - Т1 и Т2. В таблице Т1 поля а1,а2,...,а20, в таблице Т2 поля а1,а2,...,а5. Как КРАСИВО и с оптимизацией оставить в базе Т1 только те записи, которых нет в Т2 (интересуют только поля а1-а5)? Структура полей абсолютно одинаковая. Формулируй задачу правильно. Нет такого действия "оставить". Правильно понимаю: "Удалить в Т1 записи которые есть в T2" ? Как-то так Код: plaintext 1.
но такая конструкция может тормозить, поэтому надежнее условие заменить на такое: Код: plaintext 1.
Твои типы полей не знаю, если не символьные - приведи к символьным. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 08:35 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Dima TПосмотрел с sys(3054,11) и sys(3054,12) - не использует оптимизатор индекс для подзапроса. Как-то странно ты смотрел Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
PS: хотя если курсоры пустые, то индексы действительно не используются. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 11:09 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
ВладимирМКак-то странно ты смотрел Нормально смотрел, в отличии от некоторых. sys(3054,11) выдает: sys(3054,11)Joining intermediate result and intermediate result using index tag F2 И толку нам от индекса по табличке в 20 записей, когда будет скан 6 млн. записей? PS Если оптимизатор работал правильно на подзапросах, то все бы порешалось тут ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 12:15 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Макс_ПЕсть две таблицы - Т1 и Т2. В таблице Т1 поля а1,а2,...,а20, в таблице Т2 поля а1,а2,...,а5. Как КРАСИВО и с оптимизацией оставить в базе Т1 только те записи, которых нет в Т2 (интересуют только поля а1-а5)? Структура полей абсолютно одинаковая. Код: plaintext 1. 2. 3. 4.
... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 12:45 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Dima TВладимирМКак-то странно ты смотрел Нормально смотрел, в отличии от некоторых. sys(3054,11) выдает: sys(3054,11)Joining intermediate result and intermediate result using index tag F2 И толку нам от индекса по табличке в 20 записей, когда будет скан 6 млн. записей? Два момента. Dima Tне использует оптимизатор индекс для подзапроса Тем не менее, оптимизатор показывает, что индекс используется и именно для подзапроса. Ну, хорошо, пусть ты не корректно сформулировал свою мысль. Но ведь есть еще фраза sys(3054,11) Joining intermediate result and intermediate result using index tag F2 Т.е. оптимизатор не раскрывает, как именно он получил этот самый "Joining intermediate resalt". Какие индексы использовал или НЕ использовал для его получения. Очевидно же, что при стандартном INNER JOIN некие индексы должны использоваться. Однако оптимизатор этого не показывает! Т.е., строго говоря, делать выводы в данном случае опираясь лишь на SYS(3054) - несколько самонадеяно. Собственно, проще было бы провести эксперимент на реальных данных. Однако, как мне кажется, Макс_П это сделать не в состоянии (он явно не понимает о чем речь). И именно поэтому ничего "там" не порешалось, поскольку он не понимает о каких индексах идет речь. Да и все эти "игры" с VAL() и STR() говорят о том же. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 13:15 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
ВладимирМDima Tне использует оптимизатор индекс для подзапроса Тем не менее, оптимизатор показывает, что индекс используется и именно для подзапроса. Использует оптимизатор индекс, только не тот какой надо. Оптимизатор криво работает с подзапросом. Оптимизатор по разному отрабатывет на подзапрос и на JOIN. Хотя и пытается переделать на JOIN: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
Я считаю это недоделка в оптимизаторе, результат подзапроса всегда меньше таблицы из которой выборка идет. ВладимирМСобственно, проще было бы провести эксперимент на реальных данных. Я так и делал, взял свою табличку 50 млн.записей и пробовал запросы с аналогичным синтаксисом. Подзапрос тормозит. Диспетчер задач это подтверждает у меня: при подзапросе качается 20 Мб, при JOIN и макроподстановке 450 кб. У Макс_П тоже подзапрос тормозит раз с макроподстановкой стало 2 сек. вместо минуты. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 14:18 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Dima TДиспетчер задач это подтверждает у меня: при подзапросе качается 20 Мб, при JOIN и макроподстановке 450 кб. Некорректное сравнение: сравнивать подзапрос с отсутствием подзапроса. Результат слишком очевиден. Мне кажется, что стоит обратить внимание на то, СКОЛЬКО РАЗ будет выполнен подзапрос. И заменять подзапрос макроподстановкой - частное решение. В целом, если решать задачу часто и на больших объемах - без подзапроса никак. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 14:41 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Banditos, не буду комментировать твой пост. В топике речь о конкретном запросе, а не об использовании подзапросов в целом. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 14:52 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Dima TBanditos, не буду комментировать твой пост. В топике речь о конкретном запросе, а не об использовании подзапросов в целом. Ну, это по желанию. Но я бы таки рекомендовал попробовать варианты: Код: plaintext 1. 2. 3. 4. 5.
Это так, без учета индексов и прочее. На чистую, так сказать, выборку... Иначе, право, немного странно слышать обсуждение насчет необходимых индексов под "не очень" селекты. Всегда пробовал сначала довести до ума сами селекты... ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 15:32 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Ну, и еще про самый простой вариант забыл: Код: plaintext 1.
ЗЫ. Но это уже почти подсказка для индексов... ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 15:51 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
BanditosИначе, право, немного странно слышать обсуждение насчет необходимых индексов под "не очень" селекты. Всегда пробовал сначала довести до ума сами селекты... Так и надо было сразу селекты предлагать, а не общие фразы писать. Не люблю обсуждать сферических коней в вакууме. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 16:10 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
Dima TИспользует оптимизатор индекс, только не тот какой надо. Да нет же. Он показывает какой индекс использует для фильтрации промежуточного объединения, но не показывает использует ли какой-либо индекс при создании этого самого промежуточного объединения. Dima TЯ считаю это недоделка в оптимизаторе, результат подзапроса всегда меньше таблицы из которой выборка идет. Если речь идет о данном конкретном запросе, то, конечно, результат подзапроса меньше основной таблицы. Но ведь в общем случае это не известно! Хотя, согласен, что здесь что-то не доработано... Dima TВладимирМСобственно, проще было бы провести эксперимент на реальных данных. Я так и делал, взял свою табличку 50 млн.записей и пробовал запросы с аналогичным синтаксисом. Подзапрос тормозит. Диспетчер задач это подтверждает у меня: при подзапросе качается 20 Мб, при JOIN и макроподстановке 450 кб.У Макс_П тоже подзапрос тормозит раз с макроподстановкой стало 2 сек. вместо минуты. Может быть. В данном случае меня смутила небрежность формулировок, а не конечный результат :) ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 17:42 |
|
Оптимизация SQL запроса
|
|||
---|---|---|---|
#18+
СДЕЛАЛ ТАК: Создал индексы в MyTable: Kod, Rik, Ozn. База Tmp2 уже существует. q = "Rik IN(2010,2011) AND Ozn IN(1,101)" SELECT a.* FROM MyTable a INNER JOIN Zapros b ON a.Kod=b.Kod WHERE &q INTO CURSOR Tmp1 READWRITE *--- Удаляю одинаковые записи из двух таблиц и выбираю только не помеченные к удалению cField1 = 'tmp1.a1+tmp1.a2+tmp1.a3+tmp1.a4+tmp1.a5' cField2 = 'tmp2.a1+tmp2.a2+tmp2.a3+tmp2.a4+tmp2.a5' *--- Нашёл такую конструкцию для DELETE DELETE Tmp1 FROM Tmp2 WHERE &cField1=&cField2 SELECT * FROM tmp1 WHERE NOT DELETED() INTO CURSOR Tmp ... |
|||
:
Нравится:
Не нравится:
|
|||
06.12.2011, 18:45 |
|
|
start [/forum/topic.php?fid=41&msg=37560355&tid=1583961]: |
0ms |
get settings: |
10ms |
get forum list: |
15ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
60ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
48ms |
get tp. blocked users: |
1ms |
others: | 15ms |
total: | 165ms |
0 / 0 |