简单的Firebird查询非常缓慢

8
我有一张大约有246,000条记录的表格。它有大约25列,除了一个小的blob外,所有列都是整数。
如果我在所有字段上查询这个表格。
select a.recordid, a.editcount, ect.. from ARTrans a

它在不到一秒钟内执行。但如果我只包括记录ID。
select a.recordID from ARTrans a

它需要20秒以上才能执行。大部分时间都花在了规划(自然语言处理)上,这似乎很奇怪,因为在大多数情况下,我已经在recordid上建立了索引。
我已经进行了垃圾回收、重建索引、删除索引、只添加一个RecordID索引,但仍然非常慢。
任何帮助都将不胜感激。
编辑以提供更多信息:
Firebird版本:2.5.3.26778
fbclient.dll版本:2.5.1.26351
数据库中没有其他人,我已将其移至本地。
以下是表定义:
CREATE TABLE ARTRANS
(
  RECORDID Integer NOT NULL,
  EDITCOUNT Smallint,
  CLASSIFICATION Smallint,
  TRANSID Integer,
  DATEENTERED Integer,
  CLIENTID Integer,
  TRANSTYPE Smallint,
  BILLED Smallint,
  FINALIZEID Smallint,
  INVOICEID Integer,
  INVOICENUM Integer,
  INVOICEDATE Integer,
  GROUPID Smallint,
  EXPORTED Char(1),
  TRANSVALUE Decimal(18,4),
  DESCRIPTION Blob sub_type 0,
  POSTPERIOD Smallint,
  LINKEDTRANSID Integer,
  LINKEDINVID Integer,
  LINKEDFUNDSID Integer,
  INFOONLY Smallint,
  NEEDTRANSFER Char(1),
  DESTTRANSID Integer,
  LSTTKREDIT Integer,
  SPELLNGRAMMARCHECKSTATUS Smallint
);

索引
CREATE UNIQUE INDEX IDX_ARTRANSRecID ON ARTRANS (RECORDID);

SQL语句:

SELECT a.RECORDID FROM ARTRANS a

计划(flamerobin输出)
Preparing query: 
SELECT a.RECORDID 
FROM ARTRANS a
Prepare time: 20.008s
Field #01: ARTRANS.RECORDID Alias:RECORDID Type:INTEGER
PLAN (A NATURAL)


Executing...
Done.
13257 fetches, 0 marks, 76 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 0 index, 6552 seq.
Delta memory: -19204 bytes.
Total execution time: 20.025s
Script execution finished.

这个 SQL 语句运行良好:
Preparing query: 
SELECT a.RECORDID, a.EDITCOUNT, a.CLASSIFICATION,
a.TRANSID, a.DATEENTERED, a.CLIENTID, a.TRANSTYPE, a.BILLED, a.FINALIZEID,
a.INVOICEID, a.INVOICENUM, a.INVOICEDATE, a.GROUPID, a.EXPORTED, 
a.TRANSVALUE, a.DESCRIPTION, a.POSTPERIOD, a.LINKEDTRANSID, a.LINKEDINVID, 
a.LINKEDFUNDSID, a.INFOONLY, a.NEEDTRANSFER, a.DESTTRANSID, a.LSTTKREDIT, 
a.SPELLNGRAMMARCHECKSTATUS, a.RDB$DB_KEY
FROM ARTRANS a

Prepare time: 0.013s
Field #01: ARTRANS.RECORDID Alias:RECORDID Type:INTEGER
Field #02: ARTRANS.EDITCOUNT Alias:EDITCOUNT Type:SMALLINT
Field #03: ARTRANS.CLASSIFICATION Alias:CLASSIFICATION Type:SMALLINT
Field #04: ARTRANS.TRANSID Alias:TRANSID Type:INTEGER
Field #05: ARTRANS.DATEENTERED Alias:DATEENTERED Type:INTEGER
Field #06: ARTRANS.CLIENTID Alias:CLIENTID Type:INTEGER
Field #07: ARTRANS.TRANSTYPE Alias:TRANSTYPE Type:SMALLINT
Field #08: ARTRANS.BILLED Alias:BILLED Type:SMALLINT
Field #09: ARTRANS.FINALIZEID Alias:FINALIZEID Type:SMALLINT
Field #10: ARTRANS.INVOICEID Alias:INVOICEID Type:INTEGER
Field #11: ARTRANS.INVOICENUM Alias:INVOICENUM Type:INTEGER
Field #12: ARTRANS.INVOICEDATE Alias:INVOICEDATE Type:INTEGER
Field #13: ARTRANS.GROUPID Alias:GROUPID Type:SMALLINT
Field #14: ARTRANS.EXPORTED Alias:EXPORTED Type:STRING(1)
Field #15: ARTRANS.TRANSVALUE Alias:TRANSVALUE Type:NUMERIC(18,4)
Field #16: ARTRANS.DESCRIPTION Alias:DESCRIPTION Type:BLOB SUB_TYPE 0
Field #17: ARTRANS.POSTPERIOD Alias:POSTPERIOD Type:SMALLINT
Field #18: ARTRANS.LINKEDTRANSID Alias:LINKEDTRANSID Type:INTEGER
Field #19: ARTRANS.LINKEDINVID Alias:LINKEDINVID Type:INTEGER
Field #20: ARTRANS.LINKEDFUNDSID Alias:LINKEDFUNDSID Type:INTEGER
Field #21: ARTRANS.INFOONLY Alias:INFOONLY Type:SMALLINT
Field #22: ARTRANS.NEEDTRANSFER Alias:NEEDTRANSFER Type:STRING(1)
Field #23: ARTRANS.DESTTRANSID Alias:DESTTRANSID Type:INTEGER
Field #24: ARTRANS.LSTTKREDIT Alias:LSTTKREDIT Type:INTEGER
Field #25: ARTRANS.SPELLNGRAMMARCHECKSTATUS Alias:SPELLNGRAMMARCHECKSTATUS Type:SMALLINT
Field #26: ARTRANS.DB_KEY Alias:DB_KEY Type:STRING(8)
PLAN (A NATURAL)


Executing...
Done.
1135 fetches, 0 marks, 7 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 0 index, 560 seq.
Delta memory: 25852 bytes.
Total execution time: 0.047s
Script execution finished.

此外,我应该补充说明有246804条记录,并且获取计数几乎花费了一分钟的时间。
Preparing query: SELECT count(*) FROM ARTRANS a
Prepare time: 52.614s
Field #01: .COUNT Alias:COUNT Type:INTEGER
PLAN (A NATURAL)


Executing...
Done.
499643 fetches, 0 marks, 3016 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 0 index, 246804 seq.
Delta memory: -18576 bytes.
Total execution time: 52.716s
Script execution finished.

更新:
如果我删除 blob 列,性能就会恢复。如果我保留它并将所有值置为 NULL,则性能仍然很快。如果我更新每条记录的 blob 字段以包含一个大小为 20 字节的流,性能就会再次降至 20 多秒来执行简单查询。
select a.RecordID from ARTrans a

我进一步删除了除了blob字段和recordID以外的所有列,但仍然感到很慢。似乎这种情况以前应该已经出现过了,非常奇怪。

什么版本的FB?你能给我们展示确切的查询吗?(我相当确定你写的第二个查询是一个错误,它提到了你没有定义的别名。)具体的计划如何? - pilcrow
刚刚添加了版本2.5。 - cjmarques
如果在慢查询中添加magic RDB$DB_KEY(物理记录位置),并从快速查询中删除它,性能会发生什么变化? - pilcrow
1
我不明白为什么选择单列会更慢。然而,Firebird无法仅从索引中满足查询,它总是必须读取行以检查它是否对当前事务可见。因此,如果您不应用条件,则自然是唯一的计划。 - Mark Rotteveel
2
我建议您先升级到Firebird 2.5.5,看看是否可以解决问题。 - Mark Rotteveel
显示剩余6条评论
1个回答

2
为了提高性能,创建一个仅包含ID和BLOB字段的单独表格,并且仅在需要此BLOB字段时将其与您的表格连接。如果您需要计算行数,请使用count(RECORDID)(因为它是索引并且对所有行都不为空)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接