Lookup、Scan 和 Seek 有什么区别?
What is the difference between Lookup, Scan and Seek?
所以我找到了这个查询
SELECT MAX(us.[last_user_lookup]) as [last_user_lookup], MAX(us.[last_user_scan])
AS [last_user_scan], MAX(us.[last_user_seek]) as [last_user_seek]
from sys.dm_db_index_usage_stats as us
where us.[database_id] = DB_ID() AND us.[object_id] = OBJECT_ID('tblName')
group by us.[database_id], us.[object_id];
当我在 sys.dm_db_index_usage_stats 上查找文档时,它只说
last_user_seek datetime Time of last user seek
last_user_scan datetime Time of last user scan.
last_user_lookup datetime Time of last user lookup.
...
Every individual seek, scan, lookup, or update on the specified index by one query execution is counted as a use of that index and increments the corresponding counter in this view. Information is reported both for operations caused by user-submitted queries, and for operations caused by internally generated queries, such as scans for gathering statistics.
现在我明白了,当我 运行 查询时,它获得了这 3 个字段的最高时间,因为 sys.dm_db_index_usage_stats
可以有重复的 database_id
和 object_id
其中一个或更多的字段也可能是 NULL
(所以你可以只输入 SELECT TOP 1 ... ORDER BY last_user_seek, last_user_scan, last_user_lookup DESC
否则你可能会丢失数据)但是当我 运行 它时我得到的值像
NULL | 2017-05-15 08:56:29.260 | 2017-05-15 08:54:02.510
但我不明白用户用这些值表示的 table 做了什么。
那么 Lookup、Scan 和 Seek 的区别是什么?
这些操作的基本区别:
假设您有两个表。表A和表B。这两个表都包含超过 1000 000 行,并且都在 Id 列上有聚簇索引。 TableB 在代码列上也有非聚集索引。 (请记住,您的非聚集索引始终指向聚集索引的页面...)
求:
假设您只需要 TableA 中的 1 条记录,并且您的聚簇索引位于列 Id
上。
查询应如下所示:
SELECT Name
FROM TableA
WHERE Id = 1
您的结果包含的完整数据集不到 15%(介于 10-20 之间,视情况而定)...Sql服务器在此场景中执行索引查找。 (优化器已找到一个有用的索引来检索数据)
扫描:
比如你的查询需要TableA中超过15%的数据,那么就需要扫描整个索引来满足查询。
让我们考虑一下 TableB 将 TableA Id
列作为来自 TableA 的外键,并且 TableB 包含来自 TableA 的所有 Id
s。查询应如下所示:
SELECT a.Id
FROM TableA a
JOIN TableB b ON a.Id = b.TableAId
或者只是
SELECT *
FROM TableA
对于 TableA 上的索引 SQL 服务器执行使用索引扫描。因为所有数据(页面)都需要满足查询...
查找:
让我们考虑一下 TableB 有列 dim
和列 code
以及 code
上的非聚集索引(正如我们提到的)。
SQL 服务器在需要从数据页中检索非关键数据时将使用查找,并使用非聚集索引来解析查询。
例如,可以在查询中使用键查找,例如:
SELECT id, dim
FROM TableB
WHERE code = 'codeX'
- 可以通过覆盖索引来解决(包括
dim
到非聚集索引)
所以我找到了这个查询
SELECT MAX(us.[last_user_lookup]) as [last_user_lookup], MAX(us.[last_user_scan])
AS [last_user_scan], MAX(us.[last_user_seek]) as [last_user_seek]
from sys.dm_db_index_usage_stats as us
where us.[database_id] = DB_ID() AND us.[object_id] = OBJECT_ID('tblName')
group by us.[database_id], us.[object_id];
当我在 sys.dm_db_index_usage_stats 上查找文档时,它只说
last_user_seek datetime Time of last user seek last_user_scan datetime Time of last user scan. last_user_lookup datetime Time of last user lookup.
...
Every individual seek, scan, lookup, or update on the specified index by one query execution is counted as a use of that index and increments the corresponding counter in this view. Information is reported both for operations caused by user-submitted queries, and for operations caused by internally generated queries, such as scans for gathering statistics.
现在我明白了,当我 运行 查询时,它获得了这 3 个字段的最高时间,因为 sys.dm_db_index_usage_stats
可以有重复的 database_id
和 object_id
其中一个或更多的字段也可能是 NULL
(所以你可以只输入 SELECT TOP 1 ... ORDER BY last_user_seek, last_user_scan, last_user_lookup DESC
否则你可能会丢失数据)但是当我 运行 它时我得到的值像
NULL | 2017-05-15 08:56:29.260 | 2017-05-15 08:54:02.510
但我不明白用户用这些值表示的 table 做了什么。
那么 Lookup、Scan 和 Seek 的区别是什么?
这些操作的基本区别:
假设您有两个表。表A和表B。这两个表都包含超过 1000 000 行,并且都在 Id 列上有聚簇索引。 TableB 在代码列上也有非聚集索引。 (请记住,您的非聚集索引始终指向聚集索引的页面...)
求:
假设您只需要 TableA 中的 1 条记录,并且您的聚簇索引位于列 Id
上。
查询应如下所示:
SELECT Name
FROM TableA
WHERE Id = 1
您的结果包含的完整数据集不到 15%(介于 10-20 之间,视情况而定)...Sql服务器在此场景中执行索引查找。 (优化器已找到一个有用的索引来检索数据)
扫描:
比如你的查询需要TableA中超过15%的数据,那么就需要扫描整个索引来满足查询。
让我们考虑一下 TableB 将 TableA Id
列作为来自 TableA 的外键,并且 TableB 包含来自 TableA 的所有 Id
s。查询应如下所示:
SELECT a.Id
FROM TableA a
JOIN TableB b ON a.Id = b.TableAId
或者只是
SELECT *
FROM TableA
对于 TableA 上的索引 SQL 服务器执行使用索引扫描。因为所有数据(页面)都需要满足查询...
查找:
让我们考虑一下 TableB 有列 dim
和列 code
以及 code
上的非聚集索引(正如我们提到的)。
SQL 服务器在需要从数据页中检索非关键数据时将使用查找,并使用非聚集索引来解析查询。
例如,可以在查询中使用键查找,例如:
SELECT id, dim
FROM TableB
WHERE code = 'codeX'
- 可以通过覆盖索引来解决(包括
dim
到非聚集索引)