Question

I have a problem with indexes in my firebird query.

Below is my query.

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

As you see, in order by section, we use desc. I have an descending index, but my query plan does not use it. It only use index Table A (a.objid) and Table B (b.item_id, b.wh_id) Is there something i missed? What index do you think should i create?

Index for Table A (mm_itrghd)

(TR_CODE, DOC_ID) Ascending (OBJID) Ascending (TR_CODE) Ascending (POSTDATE) Ascending (POSTDATE, OBJID) Ascending (POSTDATE, OBJID) Descending

Index for Table B (mm_itrgdt)

(HEADER_ID) Ascending (ITEM_ID) Ascending (WH_ID) Ascending (LOT_NO) Ascending (SERIAL_NO, ITEM_ID) Ascending (HEADER_ID, ITEM_ID, WH_ID, SERIAL_NO, LOT_NO) Ascending (HEADER_ID, ITEM_ID, WH_ID) Ascending (CALCTYP, OBJID) Ascending (ITEM_ID, WH_ID) Ascending (CALCTYP, OBJID, ITEM_ID, WH_ID) Ascending (CALCTYP, OBJID) Descending (OBJID, ITEM_ID, WH_ID) Descending (OBJID) Descending

Thanks in advance

Regards, Reynaldi

Was it helpful?

Solution

First of all update indices statistics because Firebird relay on it when choosing what index to use and what not. Either do backup-restore cycle for database or execute following code:

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

Check the query plan after that. If index is not used it is because Firebird thinks that its usage will do more harm then help. You can either specify plan for query manually or try to rewrite it.

In your case you can get rid of OR condition using UNION operator:

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

OTHER TIPS

It's just a gut feeling, but try to also select b.objid

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top