Мой план запросов Firebird не использует правильный индекс
У меня проблема с индексами в моем запросе firebird.
Ниже мой запрос.
SELECT a.objid,
b.running_qty,
b.running_qty2,
b.running_totalcost,
b.running_lastcost
FROM mm_itrghd a,
mm_itrgdt b
WHERE (a.objid = b.header_id)
AND (b.item_id = 1200)
AND (b.wh_id = 1)
AND ((a.postdate < '2010-09-05 00:00:00') OR ((a.postdate = '2010-09-05 00:00:00') AND (a.objid < 50000)))
ORDER BY a.postdate desc,
a.objid desc,
b.calctyp desc,
b.objid desc
Как видите, в порядке по разделам мы используем desc. У меня есть нисходящий индекс, но мой план запросов не использует его. Используются только индексы Table A (a.objid) и Table B (b.item_id, b.wh_id). Есть ли что-то, что я пропустил? Какой индекс вы думаете, я должен создать?
Индекс для таблицы A (mm_itrghd)
(TR_CODE, DOC_ID) По возрастанию (OBJID) По возрастанию (TR_CODE) По возрастанию (POSTDATE) По возрастанию (POSTDATE, OBJID) По возрастанию (POSTDATE, OBJID) По убыванию
Индекс для таблицы B (mm_itrgdt)
(HEADER_ID) По возрастанию (ITEM_ID) По возрастанию (WH_ID) По возрастанию (LOT_NO) По возрастанию (SERIAL_NO, ITEM_ID) По возрастанию (HEADER_ID, ITEM_ID, WH_ID, SERIAL_NO, LOT_NO) По возрастанию (HEADER_ID, ITID_ID_ID_ID), WH_ID) По возрастанию (CALCTYP, OBJID, ITEM_ID, WH_ID) По возрастанию (CALCTYP, OBJID) По убыванию (OBJID, ITEM_ID, WH_ID) По убыванию (OBJID) По убыванию
заранее спасибо
С уважением, Рейнальди
2 ответа
Прежде всего обновите статистику индексов, потому что Firebird ретранслирует ее при выборе того, какой индекс использовать, а какой нет. Либо выполните цикл резервного копирования-восстановления базы данных, либо выполните следующий код:
EXECUTE BLOCK
AS
DECLARE VARIABLE IDX VARCHAR(31);
BEGIN
FOR
SELECT rdb$index_name FROM rdb$indices
WHERE NOT rdb$index_name LIKE 'RDB$%'
INTO :idx
DO BEGIN
EXECUTE STATEMENT 'update statistics ' || :idx
WITH AUTONOMOUS TRANSACTION;
END
END
Проверьте план запроса после этого. Если индекс не используется, это потому, что Firebird считает, что его использование принесет больше вреда, чем помощи. Вы можете указать план запроса вручную или попробовать переписать его.
В вашем случае вы можете избавиться от ИЛИ с помощью оператора UNION:
select
a.postdate,
a.objid,
b.calctyp,
b.objid,
b.running_qty,
b.running_qty2,
b.running_totalcost,
b.running_lastcost
from
mm_itrghd a join mm_itrgdt b
on a.objid=b.header_id
where
(b.item_id=1200)
and (b.wh_id=1)
and (a.postdate<'2010-09-05 00:00:00')
union all
select
a.postdate,
a.objid,
b.calctyp,
b.objid,
b.running_qty,
b.running_qty2,
b.running_totalcost,
b.running_lastcost
from
mm_itrghd a join mm_itrgdt b
on a.objid=b.header_id
where
(b.item_id=1200)
and (b.wh_id=1)
and (a.postdate='2010-09-05 00:00:00')
and (a.objid<50000)
order by
1 desc, 2 desc, 3 desc, 4 desc
Это просто внутреннее чувство, но попробуйте также выбрать b.objid