我只是好奇。
假设您有一个包含100万条记录/行的表。
select order_value from store.orders
该表在实际查询时间内是1个字段,2个字段还是100个字段是否有所不同?我的意思是除“ order_value”以外的所有字段。
现在,我正在将数据推送到数据仓库。有时我将字段转储到表中,“将来可能在某天使用”-但是现在没有任何查询。这些“外部”字段会直接或间接影响不包含它们的选择语句吗(否*我的意思是)?
我只是好奇。
假设您有一个包含100万条记录/行的表。
select order_value from store.orders
该表在实际查询时间内是1个字段,2个字段还是100个字段是否有所不同?我的意思是除“ order_value”以外的所有字段。
现在,我正在将数据推送到数据仓库。有时我将字段转储到表中,“将来可能在某天使用”-但是现在没有任何查询。这些“外部”字段会直接或间接影响不包含它们的选择语句吗(否*我的意思是)?
Answers:
这实际上取决于索引和数据类型。
以Stack Overflow数据库为例,Users表如下所示:
它在ID列上具有PK / CX。因此,这是按ID排序的整个表数据。
使用该索引作为唯一索引,SQL必须将整个内容(没有LOB列)读取到内存中(如果还不存在)。
DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.
SET STATISTICS TIME, IO ON
SELECT u.Id
INTO #crap1
FROM dbo.Users AS u
统计时间和io配置文件如下所示:
Table 'Users'. Scan count 7, logical reads 80846, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 2406 ms, elapsed time = 446 ms.
如果我仅在ID上添加其他非聚集索引
CREATE INDEX ix_whatever ON dbo.Users (Id)
我现在有一个更小的索引,可以满足我的查询要求。
DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.
SELECT u.Id
INTO #crap2
FROM dbo.Users AS u
此处的个人资料:
Table 'Users'. Scan count 7, logical reads 6587, physical reads 0, read-ahead reads 6549, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server Execution Times:
CPU time = 2344 ms, elapsed time = 384 ms.
我们能够执行更少的读取操作并节省一点CPU时间。
如果没有有关表定义的更多信息,我将无法真正尝试重现您要更好地衡量的内容。
但是您是说,除非该孤列上没有特定的索引,否则还会扫描其他列/字段吗?这仅仅是行存储表设计固有的缺点吗?为什么要扫描不相关的字段?
是的,这特定于行存储表。数据按行存储在数据页上。即使页面上的其他数据与查询无关,也需要将整个行>页面>索引读入内存。我不会说对“其他列”进行“扫描”,就像扫描它们所在的页面一样,以检索与查询相关的它们上的单个值。
以ol'电话簿示例为例:即使您只是在阅读电话号码,翻页时,您也将在姓氏,名字,地址等信息中加上电话号码。
这取决于表结构和可用索引。
情况A:通用(行存储)表,没有索引(order_value)
。
唯一可能的执行计划是读取整个表(当2列对200列时,当然有很大的不同,因此,几列对几千个字节宽)。
情况B:公用表中有一个(order_value)
包含该列的索引或其他一些索引。
现在有一个更好的计划,扫描整个索引(其中一个)-当然,它比整个表要窄得多,只有几个字节。如果表有2或200列,则无关紧要。仅索引被扫描。
案例C:这是一个列存储表。
顾名思义,这些表的结构是按列而不是按行的。不需要任何索引,表设计本身适合读取整列。