use*_*579 2 sql-server sql-server-2005 sql-server-2008 sql-server-2008-r2 sql-server-2012
指数创建策略是什么?
是否可以在 SQL Server 中的同一列上创建多个非聚集索引?
在同一列上创建集群和非集群怎么样?
非常抱歉,但索引对我来说非常混乱。
有什么方法可以找出 SQL Server 中的估计查询执行时间吗?
这些词很有逻辑性,你很快就能学会。:)
通俗地说,SEEK 意味着寻找记录的精确位置,这就是当您要搜索的列已建立索引并且您的过滤器(WHERE 条件)足够准确时 SQL Server 会执行的操作。
SCAN 意味着更大范围的行,查询执行规划器估计获取整个范围比单独查找每个值更快。
是的,您可以在同一字段上有多个索引,有时这是一个非常好的主意。使用索引并使用查询执行计划器来确定会发生什么(SSMS 中的快捷键:Ctrl + M)。您甚至可以运行同一查询的两个版本,执行计划器将轻松显示每个版本占用了多少资源和时间,使优化变得非常容易。
但要扩展一下这些,假设您有一个像这样的地址表,并且它有超过 10 亿条记录:
CREATE TABLE ADDRESS
(ADDRESS_ID INT -- CLUSTERED primary key ADRESS_PK_IDX
, PERSON_ID INT -- FOREIGN KEY, NONCLUSTERED INDEX ADDRESS_PERSON_IDX
, CITY VARCHAR(256)
, MARKED_FOR_CHECKUP BIT
, **+n^10 different other columns...**)
Run Code Online (Sandbox Code Playgroud)
现在,如果您想查找人员 12345 的所有地址信息,PERSON_ID 上的索引是完美的。由于表的同一行上有大量其他数据,因此创建非聚集索引来覆盖所有其他列以及 PERSON_ID 会效率低下且消耗空间。在这种情况下,SQL Server 将在 PERSON_ID 中的索引上执行索引 SEEK,然后使用它对 ADDRESS_ID 中的聚集索引执行键查找,并从那里返回同一行上所有其他列中的所有数据。
但是,假设您要搜索一个城市中的所有人员,但不需要其他地址信息。这次,最有效的方法是在 CITY 上创建索引,并使用 INCLUDE 选项覆盖 PERSON_ID。这样,单个索引查找/扫描将返回您需要的所有信息,而无需检查同一行上 PERSON_ID 数据的 CLUSTERED 索引。
现在,假设这两个查询都是必需的,但由于有 10 亿条记录,仍然相当繁重。但有一个特殊的查询需要非常非常快。该查询需要地址上已被 MARKED_FOR_CHECKUP 且必须居住在纽约的所有人员(忽略任何检查意味着,这并不重要)。现在您可能想在 MARKED_FOR_CHECKUP 和 CITY 上创建第三个过滤索引,其中 INCLUDE 覆盖 PERSON_ID,过滤器显示 CITY = 'New York' 且 MARKED_FOR_CHECKUP = 1。这个索引会非常快,因为它只覆盖查询满足这些确切条件,因此与其他索引相比,只需要处理一小部分数据。
(这里免责声明,请记住查询执行计划器并不愚蠢,它可以一起使用多个非聚集索引来产生正确的结果,因此上面的示例可能不是最好的可用示例,因为很难想象何时需要3 个不同的索引覆盖同一列,但我相信您已经明白了。)
索引的类型、它们的列、包含的列、排序顺序、过滤器等完全取决于具体情况。您将需要创建覆盖索引来满足几种不同类型的查询,以及专门为单个重要查询创建的自定义索引。每个索引都会占用 HDD 上的空间,因此创建无用的索引是一种浪费,并且每当数据模型发生更改时都需要额外的维护,并且会在碎片整理和统计更新操作上浪费时间......所以您不想只对所有内容都建立索引任何一个。
尝试、学习并找出最适合您需求的方法。