14.01.2011 16:56, Александр Свириденков пишет:

После пересчета статистики, первый запрос и правда стал давать
нормальный план
PLAN JOIN (CR INDEX (PK_CONT_RES), CT INDEX (RDB$PRIMARY13))

Ну и замечательно.

Но если в него поставить cr.resource is null то один фиг получаем
полное чтение CONT_RES по индексу

Т.е. речь про:

select * from cont_res cr join contracts ct on cr.cont_id=ct.cont_id
where cr.serv_id=14 and cr.resource is null

?

И тут же получаем полное индексированное чтение CONT_RES

Так полное или индексированное?
По индексу, но количество чтений=количеству записей в таблице

Кажется, картина проясняется. См. ниже.

Была бы сермяжная правда в твоих словах, если бы при попытке удалить
PK использующийся в препарированном
запросе, не получал бы со 100% вероятностью Object ... in use
Так что вы уж или крестик снимите...(с) :)

Твоя правда :-) Кстати, NOT NULL ты таки снять можешь (если там UK, а не PK). Но не удалить PK, это да.

Кроме того, мне казалось что с какой-то версии FB уже умеет искать
NULL по индексу

Он всегда это умел. Просто раньше там проблемы были.

Насколько я понимаю, тут засада в композитном индексе, где NULL - не последний сегмент. Я недавно это объяснял Болтику, цитирую:

"Это особенность реализации нуллов в индексах. Для ASC-индексов нуллы хранятся как ключи нулевой длины. Поэтому при поиске на частичное соответствие (полей в индексе больше чем в запросе) нулл будет равен любому другому ключу. Аналогия для индекса с 4 сегментами:

A = a and B = b and C = c : field like 'abc%'
A = a and B = b and C is null : field like 'ab%'

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

Таким образом, де-факто имеем поиск лишь по первому сегменту композитного индекса, а им выбираются все 100% значений.

Попробуй пересоздать композитный PK как DESC-индекс. В этом случае нуллы хранятся в виде 0xFF и все должно работать как ожидается.

Ну, или если ты заранее знаешь, что эта выборка по PK фиктивная, то добавь в предикат для CONT_RES любое значения столбца CONT_ID, тогда индексный ключ станет полным и нуллы начнут искаться (и не находиться).


Дмитрий

Ответить