这个执行计划是重新思考我的主键的动机

时间:2009-05-12 12:11:40

标签: sql clustered-index

当我进入当前(雇主)公司时,设计了一个新的数据库模式,并将成为将要/将要创建的许多未来工具的基础。 凭借我有限的SQL知识,我认为该表设计得相当好。 我唯一担心的是几乎每个表都有一个多部分主键。每个表至少有一个CustomerId和它自己的密钥。虽然这些确实是为某个记录定义的,但我觉得多个键(我们在这里谈论四倍)的效率非常低。

今天,我看到一些简单的重复查询无法想象的CPU使用率,该查询连接两个表,从第一个表中选择一个字符串字段并区分它们。

select distinct(f.FIELDNAME) as fieldName
from foo f
inner join bar b
   on f.id = b.fId
where b.cId = @id;

检查执行计划(我不是EP Hero)我注意到有三个主要CPU点。截然不同(如预期的那样)和两个寻求空缺。 我个人认为指数寻求应该非常快,但它们各占成本的18%。这是正常的吗?是由于(四重)聚簇索引吗?

- UPDATE -
该查询用于创建Lucene索引。这是一周一次的处理(听起来很矛盾,我知道)。就我看来,我不能在这里重复使用任何结果。

3 个答案:

答案 0 :(得分:3)

您能否请运行以下查询并发布其输出:

SELECT  COUNT(*), COUNT(DISTINCT fieldname)
FROM    foo

SELECT  COUNT(*), COUNT(DISTINCT cId), COUNT(DISTINCT fId)
FROM    bar

这将有助于估计哪些指数最适合您的需求。

同时确保您拥有以下索引:

foo (FIELDNAME)
bar (cId, fId)

并重写您的查询:

SELECT  DISTINCT(fieldname)
FROM    foo f
WHERE   EXISTS (
        SELECT  1
        FROM    bar b
        WHERE   b.fId = f.id
                AND b.cId = @id
        )

此查询应使用f.FIELDNAME上的索引构建DISTINCT列表和bar上的索引,以过滤掉不存在的值。

答案 1 :(得分:1)

这种查询看起来很熟悉。我在这里猜测,但是,它可能会在web / winform ui上填充一个组合框,这个组合框很难被击中。

也许您应该在应用程序端缓存结果,这样您就不会经常执行它。更糟糕的情况是你可以在sql服务器端缓存它,但它是一个巨大的kludge。

答案 2 :(得分:0)

在大多数数据库中,如果未列出索引中的第一列,则不使用索引。您说customerId是每个主键的一部分,但您不会将它用于查询中的连接。要正确回答您的问题,我们确实需要查看foo和bar的create table输出,或至少show index from

也就是说,如果你改变它,你的查询可能会更快:

select distinct(f.FIELDNAME) as fieldName
from foo f
inner join bar b
   on f.id = b.fId
   and f.cId = b.cId #Using this part of the key will speed it up
where b.cId = @id;

我的评论假定您的主键按“cId,fId”排序有效,这意味着您的查询不必检查每个cId,只检查属于索引的那些cId。