SQL Firebird условно, где не используется индекс - PullRequest
0 голосов
/ 14 января 2020

Я использую Firebird SQL версия 2.1.

У меня есть строка запроса sql, в которой передаются параметры. Если переданное значение не в моей руке, но если оно передано, это правильный тип (Timestamp или else ..)

Теперь мой запрос выглядит так:

select r.* 
from TableA 
where r.ACTION_DATE >= iif('2019-10-09 00:00:00' is null or '2019-10-09 00:00:00' = '', r.ACTION_DATE, '2019-10-09 00:00:00')

Словом, когда передается значение, я хочу загрузить все записи, у которых дата действия больше, чем '2019-10-09 00:00:00', в противном случае получить все записи.

У меня есть индекс в столбце ACTION_DATE. Для упомянутого выше запроса индекс не применяется!

Для того же запроса без условия применяется индекс:

select r.* 
from TableA 
where r.ACTION_DATE >= '2019-10-09 00:00:00'

Ответы [ 2 ]

3 голосов
/ 14 января 2020

Выражения в столбцах обычно убивают использование индексов. Некоторые базы данных могут обрабатывать явные OR:

select r.* 
from TableA 
where r.ACTION_DATE >= '2019-10-09 00:00:00' OR
      '2019-10-09 00:00:00' IS NULL;

В противном случае UNION ALL может обработать это:

select r.* 
from TableA r
where r.ACTION_DATE >= '2019-10-09 00:00:00' 
union all
select r.*
from TableA r
where '2019-10-09 00:00:00' IS NULL;

Обратите внимание, что первый подзапрос не возвращает строк, если значение равно NULL так что нет опасности дублирования строк.

1 голос
/ 14 января 2020

Не работал с Interbase / Firebird десятилетиями, но я думаю, что правая сторона не sargable .

СУБД должна получить строку сначала , чтобы получить значение r.ACTION_DATE, чтобы оценить выражение с правой стороны, и только затем он может определить, сохранять ли строку в результате, в этот момент уже слишком поздно использовать индекс (мы уже извлекли строку, поэтому нет необходимости искать ее по индексу).

Попробуйте предварительно оценить выражение и затем использовать полученное значение в предложении WHERE (с привязкой параметра и всем этим, из конечно).


Еще одна вещь, на которую следует обратить внимание, это то, что индекс полезен только в том случае, если селективность достаточно хорошая. Если вы извлекаете слишком много строк (как правило: более 10% всей таблицы), то, как правило, быстрее просто линейно пройти всю таблицу, даже если индекс пригоден для использования.

...