SQL Server 索引最佳实践(SQL Server 2008)[关闭]
Posted
技术标签:
【中文标题】SQL Server 索引最佳实践(SQL Server 2008)[关闭]【英文标题】:SQL Server Indexing best practice (SQL Server 2008) [closed] 【发布时间】:2014-02-11 07:54:42 【问题描述】:我对选择正确的索引有一些疑问并有一些疑问:
聚集索引
什么是最好的候选人?
通常是主键,但如果主键不用于搜索,例如CustomerNo
用于搜索客户是否应该将聚集索引放在CustomerNo
上?
使用 SchemaBinding 的视图
如果有一个带有索引的视图,我读到这些没有使用,但表上的那些是。
没有意义吗?还是我错过了重点?使用“NOExpand”强制从视图而不是表中读取索引会有所不同吗?
非聚集索引
添加非聚集索引以包含所有可能的列直到达到限制是一种好习惯吗?
非常感谢您的宝贵时间。我正在阅读海量数据库,速度是必须的
【问题讨论】:
坦率地说,没有人回答您的问题。如果 CustomerNo 可以是 PK 并且此列在搜索中最常使用并且此列在大多数表中是 FK,则将其设为 PK。 ii) 其他非PK但在SEARCH中使用的列可以作为非聚集索引。其他非PK在搜索条件中使用但在选择查询中使用的可以包括在非聚集索引中。 【参考方案1】:聚集索引是(a)定义表的存储布局(表数据按聚集键物理排序)的索引,以及(b)用作“行定位器”在该表的每个非聚集索引中。
因此,聚集索引应该是
窄(4 字节是理想的,8 字节可以 - 其他都太多了) 唯一(如果您不使用唯一聚集索引,SQL Server 将向您的表添加一个 4 字节唯一符) 静态(不应更改) 最好它应该不断增加 固定为 - 例如不要在聚集索引中使用大的Varchar(x)
列
在这些要求中,INT IDENTITY
似乎是最合乎逻辑、最明显的选择。不要使用可变长度的列,不要使用多列(如果可能的话),不要使用 GUID(这是一个非常糟糕的选择,因为它的大小和随机性)
有关聚簇键和聚簇索引的更多背景信息 - 阅读 Kimberly Tripp 发布的所有内容!她是 SQL Server 中的索引女王 - 她非常了解自己的东西!
参见例如这些博文:
GUIDs as PRIMARY KEYs and/or the clustering key The Clustered Index Debate Continues... Ever-increasing clustering key - the Clustered Index Debate..........again! Disk space is cheap - that's not the point!一般来说:不要过度索引!太多的索引往往比没有更糟糕!
对于非聚集索引:我通常会为 外键 列编制索引 - 这些索引有助于 JOIN 和其他操作并使事情变得更快。
除此之外:不要在数据库中放置太多索引!必须在表上的每个 CRUD 操作上维护每个索引!这是开销 - 不要过度索引!
具有所有列表的索引是一个特别糟糕的主意,因为它确实不能用于太多 - 但会带来很多管理开销。
运行您的应用,对其进行分析 - 查看哪些操作速度较慢,尝试通过向您的表中添加一些选择性索引来优化这些操作。
【讨论】:
非常感谢您的宝贵时间和非常明确的回答。非常有趣的学习负载。谢谢【参考方案2】:聚集索引
只是添加到marc_s
的好答案,标准INT IDENTITY PK
聚集索引方法的一个例外是当您拥有Parent
Child
表时,所有子表通常总是同时被检索到父母。在这种情况下,Parent PK 按 Child 表进行聚类将减少检索子项时读取的页数。例如:
CREATE TABLE Invoice
(
-- Use the default MS Approach on the parent, viz Clustered by Surrogate PK
InvoiceID INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
-- Index Fields here
);
CREATE TABLE InvoiceLineItem
(
-- Own Surrogate Key
InvoiceLineItemID INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED,
InvoiceID INT NOT NULL FOREIGN KEY REFERENCES Invoice(InvoiceID),
-- Line Item Fields Here
);
-- But Cluster on the Parent FK
CREATE CLUSTERED INDEX CL_InvoiceLineItem ON InvoiceLineItem(InvoiceID);
非聚集索引
不,千万不要在没有仔细考虑的情况下只包含列 - 索引树需要尽可能窄。索引列的排序至关重要,并且始终确保索引的设计考虑到数据的selectivity - 您需要对数据的分布有很好的了解才能选择最佳索引。
您可以考虑使用covering indexes 来包含(最多几个)列,否则在调整性能关键型查询时,这些列需要从非聚集索引中进行书签查找回到表中。
【讨论】:
【参考方案3】:作为我使用的一个非常基本的经验法则,当您的查询将返回少量数据时使用非聚集索引,而当您的查询返回较大的结果集时使用聚集索引。
我建议你阅读Clustered Index Design Guidelines
至于索引视图:索引视图的工作方式与索引表相同。它可以提高性能,但就像索引表一样,它也可以减慢速度。
我建议你阅读Improving Performance with SQL Server 2008 Indexed Views
在一般情况下,我发现索引越少越好。您需要研究您的数据,而不仅仅是对任何事物进行索引。检查您要链接的内容,添加索引并检查执行计划。有时,您认为可以制作好的索引实际上会使事情变慢。
【讨论】:
【参考方案4】:使用 SchemaBinding 的视图
...
没有意义吗?还是我没抓住重点?
(更准确地说,索引视图,schemabinding 是一种达到目的的手段,剩下的文字更多是在谈论索引视图)
创建索引视图可能有(至少)两个原因。如果没有看到您的数据库,就无法判断其中哪些原因适用。
第一个是计算从基表计算成本高昂的中间结果。为了从该计算中受益,您需要确保您的查询使用索引。要使用索引,您需要查询视图并指定 NOEXPAND
, 或 使用 Enterprise 或 Developer 版本(在 Ent/Dev 版本上,即使查询基表也可能使用索引并且没有提到视图)
第二个原因是通过实施例如视图上的unique
约束,这可能会在基表上强制执行某种形式的条件唯一性。
第二个示例 - 假设您希望表 T 能够包含具有相同 U
值的多行 - 但在这些行中,只有一个可能被标记为 Default
。在过滤索引可用之前,这通常是通过以下方式实现的:
CREATE VIEW DRI_T_OneDefault
WITH SCHEMABINDING
AS
SELECT U
FROM S.T
WHERE Default = 1
GO
CREATE UNIQUE CLUSTERED INDEX IX_DRI_T_OneDefault on DRI_T_OneDefault (U)
关键是这些索引强制执行约束。 (在这种情况下)任何查询是否实际使用索引都没有关系。就像任何唯一约束都可以在基表上声明但从未在任何查询中实际使用一样。
【讨论】:
以上是关于SQL Server 索引最佳实践(SQL Server 2008)[关闭]的主要内容,如果未能解决你的问题,请参考以下文章