我有一个表,在应用程序的生命周期中可能有10,000到1000万行。此表包含NACSZ信息,以及其他内容,我需要编写一个查询匹配NACSZ的查询,如下所示:
select
*
from
Profiles
where
FirstName = 'chris' and
LastName = 'test' and
Address1 = '123 main st' and
City = 'chicago' and
State = 'il' and
Zip = '11111'
我正在尝试优化此查询的表,该表将在“if exists()”构造内运行,并且没有太多运气。没有索引,大约110,000行测试数据,我得到:
表'个人资料'。扫描计数1, 逻辑读取2021,物理读取0, 预读读取0,lob逻辑读取 0,lob物理读取0,lob 预读读取0。
(1行受影响)
SQL Server执行时间:CPU 时间= 16毫秒,经过时间= 70毫秒。
SQL Server执行时间:CPU 时间= 0毫秒,经过时间= 1毫秒。
执行计划表示主键上的聚簇索引扫描。我想为所有值添加一个索引,但这会产生一个相当大的键,我想尽可能避免这种情况。我的下一个想法是索引行之间会有相当不同的东西,所以我尝试在名字上编制索引(虽然我可以使用地址行1或zip,例如),所以我创建了索引:
create index ix_profiles_firstName on profiles(FirstName)
现在,当我运行相同的查询时,我得到了
表'个人资料'。扫描计数1, 逻辑读取171,物理读取0, 预读读取0,lob逻辑读取 0,lob物理读取0,lob 预读读取0。
(1行受影响)
SQL Server执行时间:CPU 时间= 0毫秒,经过时间= 52毫秒。
SQL Server执行时间:CPU 时间= 0毫秒,经过时间= 1毫秒。
显然,索引名字会产生巨大的差异。我的问题是,我如何决定是否应该将名字与姓氏和地址与邮政编码进行索引?是否有一个命令可以运行我的样本数据,它会告诉我每个字段中值的唯一性?我的理解是,我应该尝试使用最独特的索引对列进行索引以使索引最佳,正确吗?
答案 0 :(得分:3)
对于您的查询,您应该在所有列上创建复合索引:(FirstName, LastName, address1, city, state, zip)
如果您希望在SQL Server
中使用某个索引,请发出:
SELECT *
FROM Profiles WITH (INDEX (index_name))
WHERE
FirstName = 'chris' and
LastName = 'test' and
Address1 = '123 main st' and
City = 'chicago' and
State = 'il' and
Zip = '11111'
我的问题是,我该如何决定是否应该将名字与姓氏对地址与邮政编码进行索引?
索引您要过滤的所有这些值。
请注意,您可以有效地过滤索引中的第一列,例如:
SELECT *
FROM Profiles
WHERE FirstName = 'chris'
将使用索引搜索FirstName
,
SELECT *
FROM Profiles
WHERE FirstName = 'chris'
AND LastName = 'test'
将使用索引搜索FirstName
和LastName
,
SELECT *
FROM Profiles
WHERE FirstName = 'chris'
AND City = 'chicago'
将使用索引仅在FirstName
上搜索(您不在LastName
上过滤,存在差距,并且索引不能用于搜索其他列)
是否有一个命令可以运行我的示例数据,它会告诉我每个字段中值的唯一性?
SELECT COUNT(DISTINCT FirstName) / COUNT(*)
FROM Profiles
将显示FirstName
互惠选择性。
此值越大,索引的效率就越低。
我的理解是,我应该尝试使用最独特的列索引索引以使索引最佳,正确吗?
是
同样,在您的情况下,您应该索引所有列。在所有专栏中,最独特的是肯定的。
答案 1 :(得分:1)
我的问题是,我该如何决定是否应该将名字与姓氏对地址与邮政编码进行索引?
收集您打算使用的所有查询(如果这是唯一的,您就完成了)。然后将查询作为工作负载转交给索引优化向导,并查看建议。
我的理解是,我应该尝试使用最独特的列索引索引以使索引最佳,正确吗?
索引越独特,从实际表中查找的结果就越少。 索引越窄,读取的速度就越快。 (此规则说明了为什么所有条件列上的复合索引都不好)。
答案 2 :(得分:1)
如果此查询看起来很重要,那么我建议您在字段上创建一个派生列作为连接;然后在您的查询中显式创建密钥。当然它是多余的,但如果你不需要它,它可能最终会比把它弄得乱七八糟。
答案 3 :(得分:1)
你有几个选择。正如Quassnoi所说,你可以创建一个复合索引。我在略有不同的情景中使用的另一个选项是根据数据生成唯一键。在我的情况下,我正在比较地址并试图防止重复(因为我们会对任何新地址进行地理编码,每个地理编码成本为$$)。
无论如何,基本上我们接收了地址的关键部分并创建了一个新密钥(Address,State& Zip)。你可以做同样的事情,然后只对一列进行比较。
一个gottcha确保在记录更改时同步此列。您可以查看使用计算列和索引可能有助于此效果的索引。
答案 4 :(得分:0)
除了其他答案......
您将运行哪种过滤器组合?尝试覆盖最流行的组合。