Subject | RE: [firebird-support] index use when using order by |
---|---|
Author | Andrew Zenz |
Post date | 2019-09-18T01:14:17Z |
… and further, when I run the query in Flamerobin as it was in the trace substituting 999999999 for the ?:
SELECT "ID","USERNAME","USERNO","LOGDATE","LOGTIME","LOGFILE","RECORDKEY","RECORDACTION","RECORDBEFORE","RECORDAFTER" FROM "AIMLOG" WHERE ("ID" <= 9999999999 ) ORDER BY "ID" DESC
The following plan is used, still taking almost 15 seconds.
Starting transaction...
Preparing query: SELECT "ID","USERNAME","USERNO","LOGDATE","LOGTIME","LOGFILE","RECORDKEY","RECORDACTION","RECORDBEFORE","RECORDAFTER" FROM "AIMLOG" WHERE ("ID" <= 9999999999 ) ORDER BY "ID" DESC
Prepare time: 0.031s
Field #01: AIMLOG.ID Alias:ID Type:INTEGER
Field #02: AIMLOG.USERNAME Alias:USERNAME Type:STRING(12)
Field #03: AIMLOG.USERNO Alias:USERNO Type:INTEGER
Field #04: AIMLOG.LOGDATE Alias:LOGDATE Type:INTEGER
Field #05: AIMLOG.LOGTIME Alias:LOGTIME Type:INTEGER
Field #06: AIMLOG.LOGFILE Alias:LOGFILE Type:STRING(30)
Field #07: AIMLOG.RECORDKEY Alias:RECORDKEY Type:STRING(30)
Field #08: AIMLOG.RECORDACTION Alias:RECORDACTION Type:STRING(10)
Field #09: AIMLOG.RECORDBEFORE Alias:RECORDBEFORE Type:STRING(1000)
Field #10: AIMLOG.RECORDAFTER Alias:RECORDAFTER Type:STRING(1000)
PLAN SORT ((AIMLOG INDEX (AIMLOG_PK)))
Executing...
Done.
260094 fetches, 0 marks, 3914 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 129996 index, 0 seq.
Delta memory: 9549504 bytes.
Total execution time: 14.391s
Script execution finished.
I am still confused/bemused about the delay. Are my expectations, that such a query should be almost instant, unreasonable? Especially when a query such as this is almost instant:
SELECT a.ID, a.USERNAME, a.USERNO, a.LOGDATE, a.LOGTIME, a."LOGFILE", a.RECORDKEY, a.RECORDACTION, a.RECORDBEFORE, a.RECORDAFTER
FROM AIMLOG a
where a.id = 123456
Starting transaction...
Preparing query: SELECT a.ID, a.USERNAME, a.USERNO, a.LOGDATE, a.LOGTIME, a."LOGFILE", a.RECORDKEY, a.RECORDACTION, a.RECORDBEFORE, a.RECORDAFTER
FROM AIMLOG a
where a.id = 123456
Prepare time: 0.016s
Field #01: AIMLOG.ID Alias:ID Type:INTEGER
Field #02: AIMLOG.USERNAME Alias:USERNAME Type:STRING(12)
Field #03: AIMLOG.USERNO Alias:USERNO Type:INTEGER
Field #04: AIMLOG.LOGDATE Alias:LOGDATE Type:INTEGER
Field #05: AIMLOG.LOGTIME Alias:LOGTIME Type:INTEGER
Field #06: AIMLOG.LOGFILE Alias:LOGFILE Type:STRING(30)
Field #07: AIMLOG.RECORDKEY Alias:RECORDKEY Type:STRING(30)
Field #08: AIMLOG.RECORDACTION Alias:RECORDACTION Type:STRING(10)
Field #09: AIMLOG.RECORDBEFORE Alias:RECORDBEFORE Type:STRING(1000)
Field #10: AIMLOG.RECORDAFTER Alias:RECORDAFTER Type:STRING(1000)
PLAN (A INDEX (AIMLOG_PK))
Executing...
Done.
18 fetches, 0 marks, 2 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 4 index, 0 seq.
Delta memory: 20548 bytes.
Total execution time: 0.031s
Script execution finished.
Cheers,
Andrew Zenz
From:
firebird-support@yahoogroups.com [mailto:firebird-support@yahoogroups.com]
Sent: Wednesday, 18 September 2019
11:02 AM
To:
firebird-support@yahoogroups.com
Subject: RE: [firebird-support]
index use when using order by
I performed a trace and this is the result. I suspected it was doing an order by:
Preparing Statement 5694738 : SELECT "ID","USERNAME","USERNO","LOGDATE","LOGTIME","LOGTABLE","RECORDKEY","RECORDACTION","RECORDBEFORE","RECORDAFTER" FROM "AIMLOG" WHERE ("ID" <= ? ) ORDER BY "ID" DESC Time Taken:0.00 secs
Setting number of rows to fetch to 1 for Statement 5694738 Time Taken:0.00 secs
Binding Column 1 to C type SLONG for Statement 5694738 Time Taken:0.00 secs
Binding Column 2 to C type CHAR for Statement 5694738 Time Taken:0.00 secs
Binding Column 3 to C type SSHORT for Statement 5694738 Time Taken:0.00 secs
Binding Column 4 to C type SLONG for Statement 5694738 Time Taken:0.00 secs
Binding Column 5 to C type SLONG for Statement 5694738 Time Taken:0.00 secs
Binding Column 6 to C type CHAR for Statement 5694738 Time Taken:0.00 secs
Binding Column 7 to C type CHAR for Statement 5694738 Time Taken:0.00 secs
Binding Column 8 to C type CHAR for Statement 5694738 Time Taken:0.00 secs
Binding Column 9 to C type CHAR for Statement 5694738 Time Taken:0.00 secs
Binding Column 10 to C type CHAR for Statement 5694738 Time Taken:0.00 secs
Binding ? 1 with C type SLONG for Statement 5694738 Time Taken:0.00 secs
Executing prepared Statement 5694738 Time Taken:15.73 secs
Fetching Row from Statement 5694738 Return Code: 0 Time Taken:0.00 secs
HTH
Andrew Zenz
From:
firebird-support@yahoogroups.com [mailto:firebird-support@yahoogroups.com]
Sent: Wednesday, 18 September 2019
10:11 AM
To:
firebird-support@yahoogroups.com
Subject: [firebird-support] index
use when using order by
Hi everyone.
I am experiencing an unusual situation.
I have a log table for tracking user changes to records. Table is as follows:
CREATE TABLE AIMLOG
(
ID Integer NOT NULL,
USERNAME Char(12) COLLATE EN_UK,
USERNO Integer,
LOGDATE Integer,
LOGTIME Integer,
LOGTABLE Char(30) COLLATE EN_UK,
RECORDKEY Char(30) COLLATE EN_UK,
RECORDACTION Char(10) COLLATE EN_UK,
RECORDBEFORE Varchar(1000) COLLATE EN_UK,
RECORDAFTER Varchar(1000) COLLATE EN_UK,
CONSTRAINT AIMLOG_PK PRIMARY KEY (ID)
);
Using Flamerobin, if I want to find the last record I run the following query:
SELECT a.ID, a.USERNAME, a.USERNO, a.LOGDATE, a.LOGTIME, a.LOGTABLE, a.RECORDKEY, a.RECORDACTION, a.RECORDBEFORE, a.RECORDAFTER
FROM AIMLOG a
order by a.id descending
The query takes about 15 seconds because it doesn’t want to use the primary key, AIMLOG_PK. Plan below:
Starting transaction...
Preparing query: SELECT a.ID, a.USERNAME, a.USERNO, a.LOGDATE, a.LOGTIME, a.LOGTABLE, a.RECORDKEY, a.RECORDACTION, a.RECORDBEFORE, a.RECORDAFTER
FROM AIMLOG a
order by a.id descending
Prepare time: 0.015s
Field #01: AIMLOG.ID Alias:ID Type:INTEGER
Field #02: AIMLOG.USERNAME Alias:USERNAME Type:STRING(12)
Field #03: AIMLOG.USERNO Alias:USERNO Type:INTEGER
Field #04: AIMLOG.LOGDATE Alias:LOGDATE Type:INTEGER
Field #05: AIMLOG.LOGTIME Alias:LOGTIME Type:INTEGER
Field #06: AIMLOG.LOGTABLE Alias:LOGTABLE Type:STRING(30)
Field #07: AIMLOG.RECORDKEY Alias:RECORDKEY Type:STRING(30)
Field #08: AIMLOG.RECORDACTION Alias:RECORDACTION Type:STRING(10)
Field #09: AIMLOG.RECORDBEFORE Alias:RECORDBEFORE Type:STRING(1000)
Field #10: AIMLOG.RECORDAFTER Alias:RECORDAFTER Type:STRING(1000)
PLAN SORT ((A NATURAL))
Executing...
Done.
267615 fetches, 0 marks, 3818 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 0 index, 129986 seq.
Delta memory: 9460264 bytes.
Total execution time: 14.734s
Script execution finished.
Another simple query that should use the index (I would assume) but doesn’t is:
select max(a.id) from aimlog a
which uses the plan:
Starting transaction...
Preparing query: select max(a.id) from aimlog a
Prepare time: 0.015s
Field #01: .MAX Alias:MAX Type:INTEGER
PLAN (A NATURAL)
Executing...
Done.
267615 fetches, 0 marks, 3821 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 0 index, 129986 seq.
Delta memory: 9724 bytes.
Total execution time: 0.172s
Script execution finished.
The application we develop in, Clarion, uses a mechanism of SET the records in a key order (usually placing the cursor at the bottom or top of the order, in this case top), then PREVIOUS to find the highest record, then adding 1 to get the next ID. (Don’t question the method, it works in the IDE we have never had an issue), however when the application does it’s SET/PREVIOUS it takes 10 to 15 seconds to complete. I can only gather that it is doing a NATURAL read as above instead of using the index.
We don’t seem to have the issue (as far as I can tell) with other tables that use the SET/PREVIOUS mechanism.
Is it a property of the ‘order by’ to not use the index, is it a bug, is it a fault in my table definition or am I missing the point?
Firebird 2.5.7 (WI-2.5.7.27050)
Just realised I ‘should’ be using 2.5.8, but on a server running WI-V2.5.8.27089 it still uses NATURAL.
Any pointers or ideas?
Thanks.
Andrew Zenz