Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 这项执行计划是重新思考我的主键的动机吗_Sql_Clustered Index - Fatal编程技术网

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

Sql 这项执行计划是重新思考我的主键的动机吗,sql,clustered-index,Sql,Clustered Index,当我进入我目前(雇主)的公司时,设计了一个新的数据库模式,它将成为许多未来正在/将要创建的工具的基础。 以我有限的SQL知识,我认为这个表设计得相当好。 我唯一关心的是几乎每个表都有一个多部分主键。每个表至少有一个CustomerId和它自己的键。虽然这些确实是对某个记录的定义,但我觉得多个键(我们这里说的是四个键)效率非常低 今天,我在一个简单的重复查询中看到了一些难以想象的CPU使用情况,该查询连接两个表,从第一个表中选择一个字符串字段并将它们区分开来 select distinct(f.F

当我进入我目前(雇主)的公司时,设计了一个新的数据库模式,它将成为许多未来正在/将要创建的工具的基础。 以我有限的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英雄)时,我注意到有三个主要的CPU点。不同的(如预期)和两个在索引上搜索。 我个人认为指数搜索应该非常快,但它们每个都占成本的18%。这正常吗?这是由于(四倍)聚集索引造成的吗

--更新--

该查询用于创建Lucene索引。这是一个一次性处理,大约每周发生一次(我知道这听起来有矛盾)。据我所知,我无法在此处重复使用任何结果。

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

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
上的索引来构建
独特的
列表,并使用
栏上的索引来过滤不存在的值。

您是否可以运行以下查询并发布其输出:

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

这种查询看起来很熟悉。我在这里猜测,但是,它可能是在web/winform ui上填充一个组合框,而这个组合框受到了相当大的冲击


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

这种查询看起来很熟悉。我在这里猜测,但是,它可能是在web/winform ui上填充一个组合框,而这个组合框受到了相当大的冲击


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

在大多数数据库中,如果索引中的第一列未列出,则不使用索引。您说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。

在大多数数据库中,如果索引中的第一列未列出,则不使用索引。您说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,只有那些是索引的一部分。

最大的问题是,查询是否需要优化,或者应用程序是否需要在调用查询时少一点攻击性。两者兼而有之是没有坏处的:)你说少一点攻击性是什么意思?我正在做的是建立一个Lucene索引,用于快速搜索。这个查询需要对我拥有的每个@id重复,我看不到任何重复使用以前结果的方法。@boris,宾果,提前获取所有id,将它们插入临时表或其他内容,并将整个kaboodle作为一个集合选择。试着一次用一个id而不是一个id来做事情谢谢你的建议,我会在当前处理完成后立即运行查询。同时,你不认为聚集索引是这里的问题吗?最大的问题是,查询是否需要优化,或者应用程序是否需要在调用查询时少一点攻击性。这两种方法都可以做到:你是说少一点攻击性?我正在做的是建立一个Lucene索引,用于快速搜索。这个查询需要对我拥有的每个@id重复,我看不到任何重复使用以前结果的方法。@boris,宾果,提前获取所有id,将它们插入临时表或其他内容,并将整个kaboodle作为一个集合选择。试着一次用一个id而不是一个id来做事情谢谢你的建议,我会在当前处理完成后立即运行查询。同时,你不认为聚集索引是这里的问题吗?是的,我明白你的意思,但我觉得在我目前的情况下不是这样。请参阅OP了解最新情况。是的,我明白你的意思,但我觉得在我目前的情况下并非如此。请参阅OP以获取更新。CustomerId尚未使用,但将在将来使用。但我觉得它应该是常规字段的一部分,应该使用一个人工键。CustomerId还没有使用,但将来会使用。但我觉得它应该是规则域的一部分,应该有一个人工键