Мой план запросов 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

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