当我进入当前(雇主)公司时,设计了一个新的数据库模式,并将成为将要/将要创建的许多未来工具的基础。 凭借我有限的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索引。这是一周一次的处理(听起来很矛盾,我知道)。就我看来,我不能在这里重复使用任何结果。
答案 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。