【问题标题】:Column with Non Clustered Index takes longer to Execute具有非聚集索引的列需要更长的时间来执行
【发布时间】:2021-09-03 01:23:16
【问题描述】:

我正在尝试了解如何正确使用非聚集索引。这是我在测试数据中发现的。

CREATE TABLE TestTable 
(
    RowID int Not Null IDENTITY (1,1),
    Continent nvarchar(100),
    Location nvarchar(100)

    CONSTRAINT PK_TestTable_RowID 
        PRIMARY KEY CLUSTERED (RowID)
)

ALTER TABLE TestTable
DROP CONSTRAINT PK_TestTable_RowID
GO

INSERT INTO TestTable
    SELECT Continent, Location
    FROM StgCovid19

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

SELECT *
FROM TestTable 
WHERE Continent = 'Asia' --551ms

CREATE NONCLUSTERED INDEX NCIContinent 
ON TestTable(Continent)

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

SELECT * 
FROM TestTable 
WHERE Continent = 'Asia' --1083ms

DROP INDEX NCIContinent
ON TestTable

CREATE NONCLUSTERED INDEX NCIContinent 
ON TestTable(Continent)
INCLUDE (Location)

DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

SELECT * 
FROM TestTable 
WHERE Continent = 'Asia' ---530ms

正如你们所看到的,如果我只在Continent 列上添加非聚集索引,它会执行查找,并且执行选择的时间也会增加一倍。

当我添加 INCLUDE (Location) 时,它比没有任何聚簇索引的时间要少。

你们能告诉我发生了什么事吗?

【问题讨论】:

  • 这是因为您的查询中的select *。它需要查找匹配行中的所有列以满足查询。通读Clustered and Nonclustered Indexes Described 以了解非聚集索引在不存在/存在聚集索引时的行为 - 请注意“行定位器”的定义。
  • 设计数据库是一项必须学习的技能。您在创建表后立即删除了主键(和聚集索引) - 为什么?这样做会让你的桌子变成一堆。如果您的列是 nvarchar,那么您的文字也应该是。养成良好的习惯。也许在这里您并不真正需要/打算使用 nvarchar 字符串 - 但您创建了表,因此您需要将代码与架构对齐。
  • @AlwaysLearning 那么是否正确,当我的查询在“RowID”和“Continent”上有 where 子句时,我应该为“RowID”(主键)和 Nonclustered 提供“Continent” '。如果在我的 SELECT 语句中我还选择了 Country 列,我应该在 nonclustered 上使用 INCLUDE?
  • @SMor 我正在学习数据仓库 ETL,有人告诉我应该在将数据插入表之前删除索引。然后在插入后再次创建索引。如果以上是真实情况,我一开始就不会创建任何索引。我会插入所有数据并创建索引

标签: sql-server indexing


【解决方案1】:

访问数据的策略取决于表结构,但也主要取决于数据分布。这就是为什么有关数据分布的统计信息存储在索引和表中的原因:

  • 在索引中,要知道键值的分布(直方图)
  • 在表格中,了解列值的分布(直方图)

计算执行计划以创建包含链接步骤的分支的树组合,这些步骤是专门用于一个操作(连接、排序、数据访问...)的算法,以构建将检索数据以响应您的需求的程序(查询)。

优化器的作用是确定在众多执行计划中,哪一个是最有趣的,使用最少的资源(内存、数据量、cpu...)。计划选择并不是系统性地更快的一种,而是在资源使用方面成本较低的一种......这个估计是由优化器根据统计偏差完成的......

您所做的测试毫无意义,因为我们不知道数据分布,并且 DBCC DROPCLEANBUFFERS 的使用具有严重的滑动效应,这在数据库利用的实际情况中是不存在的。在现实世界中,用户使用的 98% 的数据都在缓存中......!

同时测量查询的执行时间有两个问题:

  • 此指标不稳定,取决于 PC 活动,即 即使你什么都不做也很沉重。通常我们重新开始测试 至少10次,排除最慢和最快的时间和 最后计算剩余 8 个结果的平均值
  • 时间并不是唯一有趣的数字,它主要是将结果数据发送到客户端应用程序的时间。为了消除这种 时间,SSMS有一个参数,可以不执行查询 在 SSMS 中显示生成的数据集

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2013-03-19
    • 1970-01-01
    • 2020-05-22
    • 1970-01-01
    • 1970-01-01
    • 2011-10-03
    相关资源
    最近更新 更多