如果我只需要2/3列,并且我查询SELECT *而不是在select查询中提供这些列,那么在增加/减少I/O或内存方面是否会有性能下降?
如果我在不需要的情况下选择*,可能会出现网络开销。
但在select操作中,数据库引擎是始终从磁盘提取原子元组,还是仅提取select操作中请求的那些列?
如果它总是拉取一个元组,那么I/O开销是相同的。
同时,如果它拉出一个元组,那么从元组中剥离请求列可能会消耗内存。
因此,如果是这种情况,select someColumn将比select *有更多的内存开销。
发布于 2010-07-05 22:50:26
它总是拉出一个元组(除非表已经被垂直分段-分解成列的片段),所以,从性能的角度回答您提出的问题,这并不重要。但是,出于许多其他原因(如下所示),您应该始终按名称特别选择所需的列。
它总是提取一个元组,因为(在我熟悉的每个RDBMS供应商中),所有东西(包括表数据)的底层磁盘存储结构都是基于定义的I/O页(在SQL Server中,例如,每个页是8KB)。并且每个I/O读取或写入都是按页进行的。也就是说,每次写入或读取都是一个完整的数据页。
由于这种潜在的结构约束,结果是数据库中的每一行数据必须始终位于且仅位于一页上。它不能跨越多个数据页面(除了像blob这样的特殊东西,在这种情况下,实际的blob数据存储在单独的Page-chunks中,而实际的表行列只获得一个指针...)。但这些例外只是例外,通常不适用于特殊情况(对于特殊类型的数据或特殊情况下的某些优化)。
即使在这些特殊情况下,通常情况下,实际的表行数据本身(其中包含指向Blob的实际数据的指针,或其他任何内容)也必须存储在单个IO Page上……
异常。唯一可以使用Select *的地方是在Exists或Not Exists谓词子句之后的子查询中,如下所示:
Select colA, colB
From table1 t1
Where Exists (Select * From Table2
Where column = t1.colA)编辑:针对@Mike Sherer的评论,是的,这是真的,无论是在技术上,还是在美学上,都为你的特殊情况下了一点定义。首先,即使请求的列集是存储在某些索引中的列的子集,查询处理器也必须提取存储在该索引中的每一列,而不仅仅是请求的列,这也是出于同样的原因-所有I/O都必须在页中完成,并且索引数据像表数据一样存储在IO页中。因此,如果您将索引页的"tuple“定义为存储在索引中的一组列,则该语句仍然为真。
这句话在美学上是正确的,因为重点是它基于存储在I/O页中的内容来获取数据,而不是根据您请求的内容,并且无论您是在访问基表I/O页还是索引I/O页,这一点都是正确的。
有关不使用Select *的其他原因,请参阅Why is SELECT * considered harmful?:
发布于 2010-07-05 22:52:32
您永远不应该(永远不)在生产代码中使用SELECT *有几个原因:
SELECT *,你从一开始就放弃了这种可能性。在这种情况下,将从索引页检索数据(如果索引页包含所有必需的列),因此与执行SELECT *....查询相比,磁盘I/O 和内存开销要小得多。是的,一开始需要更多的输入(像SQL Prompt for SQL Server这样的工具甚至可以在这方面帮助你)--但这确实是一个没有例外的规则:永远不要在你的生产代码中使用SELECT *。永远不会。
发布于 2010-07-05 22:48:28
您应该始终只对实际需要的列执行select操作。选择less而不是more的效率永远不会降低,而且您还会遇到更少的意外副作用-比如逐个索引地访问客户端的结果列,然后通过向表中添加新列来使这些索引变得不正确。
编辑:表示访问。愚蠢的大脑还在醒着。
https://stackoverflow.com/questions/3180375
复制相似问题