Sql 使用两个字段排序时,DB2 ORDER BY查询速度较慢

Sql 使用两个字段排序时,DB2 ORDER BY查询速度较慢,sql,performance,select,db2,sql-order-by,Sql,Performance,Select,Db2,Sql Order By,我有一个DB2表,它具有以下模式: CREATE TABLE "CONTACTS" ( "ID" CHAR(36) NOT NULL, "DELETED" SMALLINT DEFAULT 0, "FIRST_NAME" VARCHAR(200), "LAST_NAME" VARCHAR(200) ); CREATE INDEX "IDX_CONTACTS_DEL_LAST" ON "CONTACTS" ("DELETED" ASC, "LA

我有一个DB2表,它具有以下模式:

CREATE TABLE "CONTACTS" (
  "ID" CHAR(36) NOT NULL, 
  "DELETED" SMALLINT DEFAULT 0, 
  "FIRST_NAME" VARCHAR(200), 
  "LAST_NAME" VARCHAR(200)
);

    CREATE INDEX "IDX_CONTACTS_DEL_LAST" ON "CONTACTS"
    ("DELETED"  ASC, 
     "LAST_NAME"    ASC) 
     MINPCTUSED 0 ALLOW REVERSE SCANS PAGE SPLIT SYMMETRIC COMPRESS YES;

    CREATE INDEX "IDX_CONTACT_LASTNAME" ON "CONTACTS"
    ("LAST_NAME"    ASC, 
     "DELETED"  ASC)
     MINPCTUSED 0 ALLOW REVERSE SCANS PAGE SPLIT SYMMETRIC COMPRESS YES;

    CREATE INDEX "IDX_CONT_LAST_FIRST" ON "CONTACTS"
    ("LAST_NAME"    ASC, 
     "FIRST_NAME"   ASC, 
     "DELETED"  ASC)
     MINPCTUSED 0 ALLOW REVERSE SCANS PAGE SPLIT SYMMETRIC COMPRESS YES;

    CREATE INDEX "IDX_ID_DEL" ON "CONTACTS"
    ("ID"   ASC, 
     "DELETED"  ASC)
     MINPCTUSED 0 ALLOW REVERSE SCANS PAGE SPLIT SYMMETRIC COMPRESS YES;

    CREATE UNIQUE INDEX "CONTACTSPK" ON "CONTACTS"
    ("ID"   ASC)
     MINPCTUSED 0 ALLOW REVERSE SCANS PAGE SPLIT SYMMETRIC COMPRESS YES;

    ALTER TABLE "CONTACTS" ADD CONSTRAINT "CONTACTSPK" PRIMARY KEY ("ID");
此查询工作正常(快速):

但是,在相当大(数百万行)的数据库上,速度几乎慢1000倍:

SELECT * FROM (SELECT contacts.id, contacts.first_name, contacts.last_name 
FROM contacts WHERE contacts.deleted=0 
ORDER BY contacts.last_name ASC, contacts.id ASC) 
LIMIT 21 OPTIMIZE FOR 21 ROWS
现在,我假设once
last\u name
被编入索引并具有足够的基数(确实如此),添加二级排序应该无关紧要。然而,事实证明这很重要——它使查询速度慢了一千倍。我的问题是,为什么DB2不应该只从
last\u name/deleted
索引中取前21行,这应该非常快,按
ID
对它们进行排序,然后处理它?然而,它看起来做了全表扫描,或者至少做了一些非常昂贵的事情。所以我的问题是为什么


第二个问题是,是否有一种方法可以添加二级排序字段而不会造成这种影响。原因是由于将字段添加到
联系人中
他们将有自己的索引,但将
id
添加到每个索引中看起来很浪费。当然,有些字段可能有许多记录具有相同的
姓氏
或其他值,因此为这些行设置稳定的顺序非常有用,尤其是在分页时。DB2是否保证这样的顺序而不进行二次排序?

您想要的索引位于
联系人(已删除,姓氏,id)
上。这将使用
lastname
作为排序键以及
lastname
id
对查询起作用

性能问题的原因。首先,仅使用
lastname
的快速查询使用索引。另一个可以使用索引,也可以不使用索引,但它必须获取具有相同
lastname
的所有行,然后必须按
id
对它们进行排序。毕竟,没有理由认为索引中具有相同
lastname
的前21行都具有相同的
id

这个问题可能是两件事之一。第一个问题是,一个姓氏可能有许多具有相同
id
的记录。第二个原因很简单,DB2因为存在
id
而感到困惑,并决定不使用索引


虽然它可能对查询没有帮助,但如果确实是主键,则应该将
id
声明为主键。

我查看了实际数据,虽然有一些记录具有相同的姓氏,但它们并不多,每个名称不超过2-3个。不应导致1000倍的减速。因此,出于某种原因,DB2似乎放弃了索引进行二次排序。也许您可以从查看两个查询的
EXPLAIN
输出开始?@IanBjorhovde不幸的是,EXPLAIN显示速度慢的查询不使用索引,但它无法解释为什么不使用索引以及如何使用索引。
SELECT * FROM (SELECT contacts.id, contacts.first_name, contacts.last_name 
FROM contacts WHERE contacts.deleted=0 
ORDER BY contacts.last_name ASC, contacts.id ASC) 
LIMIT 21 OPTIMIZE FOR 21 ROWS