不相关的列会影响select语句的查询时间吗?


10

我只是好奇。

假设您有一个包含100万条记录/行的表。

select order_value from store.orders

该表在实际查询时间内是1个字段,2个字段还是100个字段是否有所不同?我的意思是除“ order_value”以外的所有字段。

现在,我正在将数据推送到数据仓库。有时我将字段转储到表中,“将来可能在某天使用”-但是现在没有任何查询。这些“外部”字段会直接或间接影响不包含它们的选择语句吗(否*我的意思是)?


网络上有大量有关此方面的信息。关键是随着技术的变化获取最新信息。您要问的问题取决于您的特定设置,因此不可能给出很好的答案。要记住的一个关键点是,当我们转向SSD时,曾经对性能非常重要的许多事情不再适用。

Answers:


10

这实际上取决于索引和数据类型。

以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'电话簿示例为例:即使您只是在阅读电话号码,翻页时,您也将在姓氏,名字,地址等信息中加上电话号码。


@ jpmc26它可能会变得更糟,因为如果请求的列都是索引的一部分,则仅通过查看索引即可提供查询。如果这些列索引,它们可能会导致要加载的主记录,并且即使对于非custered表/列类型的二次记录。
克里斯托弗·舒尔茨

12

这取决于表结构和可用索引。

  • 情况A:通用(行存储)表,没有索引(order_value)

    唯一可能的执行计划是读取整个表(当2列对200列时,当然有很大的不同,因此,几列对几千个字节宽)。

  • 情况B:公用表中有一个(order_value)包含该列的索引或其他一些索引。

    现在有一个更好的计划,扫描整个索引(其中一个)-当然,它比整个表要窄得多,只有几个字节。如果表有2或200列,则无关紧要。仅索引被扫描。

  • 案例C:这是一个列存储表。

    顾名思义,这些表的结构是按列而不是按行的。不需要任何索引,表设计本身适合读取整列。


我的知识在这个问题上有点绿色。拥有行存储表是最传统的方式(例如典型的SQL Server数据库),对吗?如果只需要返回一列/字段,为什么要扫描整个表?这仅仅是行存储表设计所固有的吗?
user45867

@ user45867是的,数据存储在行中(存储在外部的一些非常大的列除外)。当SQL Server从磁盘读取数据时,它将读取整个块,而不能仅读取具有一列的部分。
ypercubeᵀᴹ
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.