Как заставить использование индекса в DB2 при использовании скалярного значения, возвращаемого подзапросом?

Запрос выполняется на огромной таблице (более 1 миллиарда записей)

Выберите Col1 из таблицы A, где иденткол> (выберите bigint(идентвал) в ParamTable)

(identval Тип данных является символом и identcol является BIGINT) Это занимает много времени и выполняет полное сканирование таблицы. Когда я заменяю подзапрос и использую числовое значение в предложении where для identcol, он начинает использовать индекс для этого столбца.

Есть ли способ заставить DB2 использовать этот индекс без указания литерального значения? (DB2 9.7 в AIX)

редактирование: я обнаружил, что МЕЖДУ работает с подзапросом и верхним значением, а также использует индекс. Также, если я удаляю явное приведение к BIGINT, оно начинает использовать индекс. Но все же хотелось бы узнать технические пояснения / указатели. Спасибо!

1 ответ

Решение

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

Когда в предикате указано буквальное значение, оптимизатор может использовать статистику распределения значений для tableA.identcol оценить, сколько строк может соответствовать условию. По-видимому, распределение таково, что, учитывая предоставленное литеральное значение, он лучше рассматривает доступ на основе индекса.

Когда вместо этого вы предоставляете подзапрос, оптимизатор не может знать, что identval будет возвращено, поэтому он делает предположение, которое в вашем случае оказывается неоптимальным.

Чтобы добиться более согласованного результата оптимизации, вам необходимо предоставить оптимизатору дополнительную информацию. Есть несколько вариантов, которые вы можете попробовать.

  1. Создать статистическое представление, что-то вроде create view sv1 as select Col1 from TableA, ParamTable where TableA.identcol > ParamTable.identval (и бросьте bigint() Исходя из вашего запроса - не нужно путать оптимизатор еще больше). Затем вам нужно будет включить оптимизацию статистического представления (alter view sv1 enable query optimization) и собирать статистику распространения (runstats on table sv1 with distribution). Однако, видя, что ParamTable содержит только одну строку, можно предположить, что она меняется довольно часто, поэтому вам нужно следить за тем, чтобы статистика обновлялась каждый раз ParamTable.identval изменения.
  2. Предоставьте оптимизатору явную оценку селективности: Select Col1 from TableA where identcol > (select bigint(identval) from ParamTable) selectivity 0.001, Прежде чем вы сможете это сделать, вам нужно установить переменную реестра DB2, включающую это поведение (db2set DB2_SELECTIVITY=ALL) и перезапустите экземпляр. 0.001 указывает долю таблицы, в данном случае 0,1%, которая удовлетворяет условию. замещать 0.001 с реалистичной оценкой доли совпадающих строк.

  3. Создать индекс на TableA (identcol, Col1) если он еще не существует (и собирать для него статистику) - это может разрешить доступ только по индексу.

Другие вопросы по тегам