powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Оптимизация SQL запроса
22 сообщений из 22, страница 1 из 1
Оптимизация SQL запроса
    #37556223
Макс_П
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день!
Подскажите, какой индекс лучше создать в базе данных(6000000 млн.записей) для максимальной работы SQL запроса со следующим условием отбора:
SELECT...WHERE VAL(Kod) IN(SELECT Kod FROM Zapros) AND Rik IN(2010,2011) AND Ozn IN(1,101)
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37556578
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
6000000 млн.записей или все-таки 6 млн.записей?
мало инфы указал.
Сколько записей под каждое подусловие попадает?
Rik IN(2010,2011)
Ozn IN(1,101)
VAL(Kod) IN(SELECT Kod FROM Zapros)

Сколько всего записей в результате запроса получается?

подозреваю что надо индекс по KOD, только запрос надо немного переделать чтобы индекс заработал. VAL() убрать как-то так:
Код: plaintext
1.
SELECT...WHERE Kod IN (SELECT str(Kod, 10) FROM Zapros)
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37556842
Макс_П
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima T6000000 млн.записей или все-таки 6 млн.записей?
мало инфы указал.
Сколько записей под каждое подусловие попадает?
Rik IN(2010,2011)
Ozn IN(1,101)
VAL(Kod) IN(SELECT Kod FROM Zapros)

Сколько всего записей в результате запроса получается?

подозреваю что надо индекс по KOD, только запрос надо немного переделать чтобы индекс заработал. VAL() убрать как-то так:
Код: plaintext
1.
SELECT...WHERE Kod IN (SELECT str(Kod, 10) FROM Zapros)

Да, записей 6 млн. Количество Kod в базе Zapros может быть до 20 записей, а результат выборки по Rik и Ozn для каждого Kod, может быть до 1000 записей. Индекс по KOD есть, убрал VAL(), как Вы и советовали, но, скорость от этого практически не поменялась(обработка идёт около 1 мин.).
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37557311
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sys(3054, 2) - выводит как работает оптимизатор. Посмотри какие индексы он берет.
Провел тест:
оптимизируется Rik IN(2010,2011), т.е. для такого условия индекс по Rik он задействует
это НЕ оптимизируется Kod IN (SELECT ..), т.е. будет перебор результата выборки по остальным условиям.

Вобщем для задействования индекса по Kod надо заменять подзапрос на макроподстановку:
генеришь список значений из Zapros в переменную lcZapros и
Код: plaintext
1.
SELECT...WHERE Kod IN(&lcZapros) ...


Тут возможна проблема с длинной запроса в символах, если будут ошибки что запрос слишком длинный, то разбивать на несколько запросов, а потом склеивать результаты.

По выбору индексов ты не сказал что я просил. Сделай такие запросы:
Код: plaintext
1.
2.
3.
SELECT...WHERE Rik IN(2010,2011)
SELECT...WHERE Ozn IN(1,101)
SELECT...WHERE VAL(Kod) IN(SELECT Kod FROM Zapros)


если запрос возвращает много записей, то индекс по этому полю будет бесполезен. Сколько значит "много" точно не скажу, думаю 20-25% от размера исходной таблицы. Если получишь более 50% то такой индекс может даже замедлять запрос.
Чем меньше записей выбирается по конкретному условию для поля тем больший эффект даст индекс по этому полю.

И условия надо расположить по мере убывания эффективности индекса, т.е. например если Ozn IN (1,101) дает наименьшее количество, то его поставить вперед:
Код: plaintext
1.
SELECT...WHERE Ozn IN(1,101) and ...
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37558264
Фотография Redrik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Макс_П,

1-ДФ? ;)
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37558928
Banditos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Макс_ПДобрый день!
Подскажите, какой индекс лучше создать в базе данных(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.
SELECT *
    FROM T1,  (SELECT Kod FROM Zapros) T2
WHERE T1.Kod = T2.Kod AND T1.Rik IN(2010,2011) AND T1.Ozn IN(1,101)



Да, неплохо бы увидеть ВЕСЬ селект. Ибо вместо звездочки невесть что стоять может....
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37559677
Макс_П
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Код: plaintext
1.
SELECT...WHERE Kod IN(&lcZapros) ...


Спасибо! Очень помог совет. Теперь программа выполняется за 2 секунды.
И, в догонку, ещё вопрос -
Есть две таблицы - Т1 и Т2. В таблице Т1 поля а1,а2,...,а20, в таблице Т2 поля а1,а2,...,а5.
Как КРАСИВО и с оптимизацией оставить в базе Т1 только те записи, которых нет в Т2 (интересуют только поля а1-а5)? Структура полей абсолютно одинаковая.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37559953
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima Tsys(3054, 2) - выводит как работает оптимизатор. Посмотри какие индексы он берет.
Провел тест:
оптимизируется Rik IN(2010,2011), т.е. для такого условия индекс по Rik он задействует
это НЕ оптимизируется Kod IN (SELECT ..), т.е. будет перебор результата выборки по остальным условиям.

Ты не туда смотрел. В данном случае надо "ловить" оптимизацию Join, а не Where. Т.е. нужно sys(3054,12). Оптимизатор показывает, что промежуточный результат объединения использует индекс в подзапросе. Другими словами, нужен индекс по тому полю, которое отбирается в позапросе.

Для конструкции

Код: plaintext
1.
... IN (SELECT Kod FROM Zapros)



Нужен индекс по полю Код в таблице Zapros.

Впрочем, оптимизатор не раскрывает использует ли он индекс по полю другой таблицы при формировании промежуточного результата объединения. Теоретически, должен был бы. Но как оно на самом деле - не известно.

PS: Как мне кажется, SYS(3054,1) и SYS(3054,2) оставлены для совместимости. Всегда для надежности надо ставить 11 или 12.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37560329
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимирМ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.
SELECT... FROM MyTable join Zapros on MyTable.Kod = str(Zapros.Kod) WHERE Rik IN(2010,2011) AND Ozn IN(1,101)


если скорость нормальная будет - лучше его используй чем макроподстановки.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37560355
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Макс_ПЕсть две таблицы - Т1 и Т2. В таблице Т1 поля а1,а2,...,а20, в таблице Т2 поля а1,а2,...,а5.
Как КРАСИВО и с оптимизацией оставить в базе Т1 только те записи, которых нет в Т2 (интересуют только поля а1-а5)? Структура полей абсолютно одинаковая.
Формулируй задачу правильно. Нет такого действия "оставить".
Правильно понимаю: "Удалить в Т1 записи которые есть в T2" ? Как-то так
Код: plaintext
1.
delete T1 from T1 join T2 on T1.a1  = T2.a1 and T1.a2 = T2.a2 ...


но такая конструкция может тормозить, поэтому надежнее условие заменить на такое:
Код: plaintext
1.
delete T1 from T1 join T2 on T1.a1 + T1.a2 ... = T2.a1 + T2.a2 ...


Твои типы полей не знаю, если не символьные - приведи к символьным.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37560556
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TПосмотрел с sys(3054,11) и sys(3054,12) - не использует оптимизатор индекс для подзапроса.


Как-то странно ты смотрел

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
create cursor t1 (f1 i)
index on f1 tag f1
insert into t1 values (1)

create cursor t2 (f2 i)
index on f2 tag f2
insert into t2 values (1)

=sys(3054,11)
select * from t1 where f1 in (select f2 from t2)



PS: хотя если курсоры пустые, то индексы действительно не используются.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37560681
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимирМКак-то странно ты смотрел

Нормально смотрел, в отличии от некоторых.
sys(3054,11) выдает:
sys(3054,11)Joining intermediate result and intermediate result using index tag F2
И толку нам от индекса по табличке в 20 записей, когда будет скан 6 млн. записей?

PS Если оптимизатор работал правильно на подзапросах, то все бы порешалось тут
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37560766
Banditos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Макс_ПЕсть две таблицы - Т1 и Т2. В таблице Т1 поля а1,а2,...,а20, в таблице Т2 поля а1,а2,...,а5.
Как КРАСИВО и с оптимизацией оставить в базе Т1 только те записи, которых нет в Т2 (интересуют только поля а1-а5)? Структура полей абсолютно одинаковая.


Код: plaintext
1.
2.
3.
4.
DELETE FROM T1 WHERE EXIST (select 1 FROM T2 
                                            WHERE T1.a1 = T2.a1 AND T1.a2 = T2.a2
                                                      AND T1.a3 = T2.a3 AND T1.a4 = T2.a4 
                                                      AND T1.a5 = T2.a5 )
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37560838
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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() говорят о том же.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37560996
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ВладимирМDima Tне использует оптимизатор индекс для подзапроса

Тем не менее, оптимизатор показывает, что индекс используется и именно для подзапроса.
Использует оптимизатор индекс, только не тот какой надо.
Оптимизатор криво работает с подзапросом.
Оптимизатор по разному отрабатывет на подзапрос и на JOIN. Хотя и пытается переделать на JOIN:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
create cursor t1 (f1 i)
index on f1 tag f1
insert into t1 values (1)
insert into t1 values (2)
insert into t1 values (3)
insert into t1 values (4)

create cursor t2 (f2 i)
index on f2 tag f2
insert into t2 values (1)

=sys(3054, 11)
select * from t1 where f1 in (select f2 from t2)
select * from t1 join t2 on t1.f1 = t2.f2


Я считаю это недоделка в оптимизаторе, результат подзапроса всегда меньше таблицы из которой выборка идет.

ВладимирМСобственно, проще было бы провести эксперимент на реальных данных.
Я так и делал, взял свою табличку 50 млн.записей и пробовал запросы с аналогичным синтаксисом. Подзапрос тормозит.
Диспетчер задач это подтверждает у меня: при подзапросе качается 20 Мб, при JOIN и макроподстановке 450 кб.
У Макс_П тоже подзапрос тормозит раз с макроподстановкой стало 2 сек. вместо минуты.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37561048
Banditos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TДиспетчер задач это подтверждает у меня: при подзапросе качается 20 Мб, при JOIN и макроподстановке 450 кб.

Некорректное сравнение: сравнивать подзапрос с отсутствием подзапроса. Результат слишком очевиден.

Мне кажется, что стоит обратить внимание на то, СКОЛЬКО РАЗ будет выполнен подзапрос.
И заменять подзапрос макроподстановкой - частное решение. В целом, если решать задачу часто и на больших объемах - без подзапроса никак.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37561073
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Banditos, не буду комментировать твой пост. В топике речь о конкретном запросе, а не об использовании подзапросов в целом.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37561182
Banditos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima TBanditos, не буду комментировать твой пост. В топике речь о конкретном запросе, а не об использовании подзапросов в целом.
Ну, это по желанию.

Но я бы таки рекомендовал попробовать варианты:
Код: plaintext
1.
2.
3.
4.
5.
SELECT t1.kod FROM t1 WHERE t1.kod in (SELECT t2.kod FROM t2) 

SELECT t1.kod FROM t1 WHERE t1.kod in (SELECT t2.kod FROM t2 WHERE t2.kod = t1.kod) 

SELECT t1.kod FROM t1, (SELECT t2.kod FROM t2) t2 WHERE t1.kod = t2.kod


Это так, без учета индексов и прочее. На чистую, так сказать, выборку...
Иначе, право, немного странно слышать обсуждение насчет необходимых индексов под "не очень" селекты. Всегда пробовал сначала довести до ума сами селекты...
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37561233
Banditos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну, и еще про самый простой вариант забыл:
Код: plaintext
1.
SELECT t1.kod FROM t1, t2 WHERE t1.kod = t2.kod


ЗЫ. Но это уже почти подсказка для индексов...
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37561282
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BanditosИначе, право, немного странно слышать обсуждение насчет необходимых индексов под "не очень" селекты. Всегда пробовал сначала довести до ума сами селекты...
Так и надо было сразу селекты предлагать, а не общие фразы писать. Не люблю обсуждать сферических коней в вакууме.
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37561522
Фотография ВладимирМ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Dima TИспользует оптимизатор индекс, только не тот какой надо.
Да нет же. Он показывает какой индекс использует для фильтрации промежуточного объединения, но не показывает использует ли какой-либо индекс при создании этого самого промежуточного объединения.

Dima TЯ считаю это недоделка в оптимизаторе, результат подзапроса всегда меньше таблицы из которой выборка идет.
Если речь идет о данном конкретном запросе, то, конечно, результат подзапроса меньше основной таблицы. Но ведь в общем случае это не известно! Хотя, согласен, что здесь что-то не доработано...

Dima TВладимирМСобственно, проще было бы провести эксперимент на реальных данных.
Я так и делал, взял свою табличку 50 млн.записей и пробовал запросы с аналогичным синтаксисом. Подзапрос тормозит.
Диспетчер задач это подтверждает у меня: при подзапросе качается 20 Мб, при JOIN и макроподстановке 450 кб.У Макс_П тоже подзапрос тормозит раз с макроподстановкой стало 2 сек. вместо минуты.
Может быть. В данном случае меня смутила небрежность формулировок, а не конечный результат :)
...
Рейтинг: 0 / 0
Оптимизация SQL запроса
    #37561638
Макс_П
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
СДЕЛАЛ ТАК:
Создал индексы в 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
...
Рейтинг: 0 / 0
22 сообщений из 22, страница 1 из 1
Форумы / FoxPro, Visual FoxPro [игнор отключен] [закрыт для гостей] / Оптимизация SQL запроса
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]