1

当我进入我当前(雇主的)公司时,设计了一个新的数据库模式,它将成为许多未来将要创建的工具的基础。凭借我有限的 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 点。不同的(如预期的那样)和两个寻求indeces。我个人认为索引搜索应该非常快,但它们每个都占用了 18% 的成本。这是正常的吗?是因为(四重)聚集索引吗?

--UPDATE--
该查询用于创建 Lucene 索引。这是一个一次性处理,大约每周发生一次(我知道这听起来很矛盾)。据我所知,我不能在这里重用任何结果。

4

3 回答 3

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来过滤掉不存在的值。

于 2009-05-12T12:21:05.350 回答
1

这种查询看起来很熟悉。我在这里猜想,但是,它可能会在受到重创的 web/winform ui 上填充一个组合框。

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

于 2009-05-12T12:29:51.893 回答
0

在大多数数据库中,如果未列出索引中的第一列,则不使用索引。您说 customerId 是每个主键的一部分,但您没有将它用于查询中的联接。要正确回答您的问题,我们确实需要查看create tablefoo 和 bar 的输出,或者至少是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,只需检查属于索引的那些。

于 2009-05-12T13:43:31.573 回答