Nee*_*asu 120 sql performance
如果我只需要2/3列并且我查询SELECT *
而不是在select查询中提供这些列,那么是否有关于更多/更少I/O或内存的性能下降?
如果我在不需要的情况下选择*,则可能存在网络开销.
但是在select操作中,数据库引擎是否始终从磁盘中提取原子元组,还是仅提取select操作中请求的那些列?
如果它总是拉取元组,那么I/O开销是相同的.
同时,如果它提取元组,则可能存在从元组中剥离所请求列的内存消耗.
因此,如果是这种情况,选择someColumn将比select*具有更多的内存开销
mar*_*c_s 108
您应该永远(从未)SELECT *
在生产代码中使用以下几个原因:
既然你没有给你的数据库任何关于你想要的提示,它首先需要检查表的定义,以确定该表上的列.该查找将花费一些时间 - 在单个查询中不多 - 但随着时间的推移它会增加
如果您只需要2/3的列,那么您需要选择1/3太多的数据,这些数据需要从磁盘检索并通过网络发送
如果您开始依赖数据的某些方面,例如返回的列的顺序,一旦重组表并添加新列(或删除现有列),您可能会得到一个令人讨厌的惊喜
在SQL Server中(不确定其他数据库),如果需要列的子集,非聚集索引总是有可能覆盖该请求(包含所需的所有列).有了a SELECT *
,你就可以从一开始就放弃这种可能性.在这种特殊情况下,数据将从索引页面中检索(如果它们包含所有必需的列),因此与执行查询相比,磁盘I/O 和内存开销会少得多SELECT *....
.
是的,它最初需要更多的输入(像SQL Prompt for SQL Server 这样的工具甚至可以帮助你) - 但这确实是一个没有任何异常的规则:不要在生产代码中使用SELECT*.EVER.
Cha*_*ana 28
它总是拉取一个元组(除非表格已被垂直分割 - 分成列块),所以,为了回答你问的问题,从性能角度来看并不重要.但是,由于许多其他原因(在下面),您应该始终按名称专门选择所需的列.
它总是拉出一个元组,因为(在我熟悉的每个供应商RDBMS中,所有内容的基础磁盘存储结构(包括表数据)都基于定义的 I/O页面(在SQL Server中,例如,每个页面为8)每个I/O读取或写入都是通过页面进行的.也就是说,每次写入或读取都是一个完整的数据页面.
由于这种潜在的结构约束,结果是数据库中的每行数据必须始终位于一个且仅一个页面上.它不能跨越多个数据页面(除了特殊的东西,比如blob,其中实际的blob数据存储在单独的Page-chunk中,而实际的表行列只能获得一个指针......).但是这些异常仅仅是异常,并且通常不适用,除非在特殊情况下(对于特殊类型的数据,或特殊情况下的某些优化)
即使在这些特殊情况下,通常也是实际的表行数据本身(包含指向Blob的实际数据的指针,或其他),它必须存储在单个IO页面上...
例外.唯一可以的地方Select *
是在一个Exists
或Not Exists
谓词子句之后的子查询中,如:
Select colA, colB
From table1 t1
Where Exists (Select * From Table2
Where column = t1.colA)
Run Code Online (Sandbox Code Playgroud)
编辑:要解决@Mike Sherer评论,是的,从技术上讲,这是真的,对你的特殊情况有一点定义,而且在审美上.首先,即使请求的列集是存储在某个索引中的列的子集,查询处理器也必须获取存储在该索引中的每个列,而不仅仅是请求的列,原因相同 - 所有I/O必须在页面和索引数据就像表数据一样存储在IO页面中.因此,如果将索引页面的"元组"定义为存储在索引中的列集,则该语句仍然为true.
并且该陈述在美学上是真实的,因为关键是它根据存储在I/O页面中的内容而不是您要求的内容来获取数据,无论您是访问基表I/O页还是索引,都是如此I/O页面.
出于其他原因不使用Select *
,请参阅 为什么被SELECT *
认为有害?:
Don*_*nie 20
您应始终只select
使用实际需要的列.选择less而不是更多的效率永远不会低,而且你也会遇到更少的意外副作用 - 比如在客户端按索引访问结果列,然后通过向表添加新列使这些索引变得不正确.
[编辑]:访问权限.愚蠢的大脑仍在醒来.
小智 7
除非您存储大量blob,否则性能不是问题.不使用SELECT*的一个重要原因是,如果您使用返回的行作为元组,则列会以模式指定的顺序返回,如果更改,则必须修复所有代码.
另一方面,如果您使用字典样式访问,那么列返回的顺序无关紧要,因为您始终按名称访问它们.
这让我想起了我正在使用的包含一列类型的表blob
; 它通常包含一个JPEG图像,Mb
大小为几个.
毋庸置疑SELECT
,除非我真的需要它,否则我没有那个专栏.让这些数据浮动 - 特别是当我选择多行时 - 只是一个麻烦.
但是,我承认我通常会查询表中的所有列.
在SQL选择期间,DB始终会引用表的元数据,无论它是SELECT*for SELECT a,b,c ......为什么?因为这是关于系统上表格的结构和布局的信息.
必须阅读此信息有两个原因.一,简单地编译语句.它需要确保至少指定一个现有的表.此外,自上次执行语句以来,数据库结构可能已更改.
现在,很明显,DB元数据被缓存在系统中,但它仍然需要处理.
接下来,元数据用于生成查询计划.每次编译语句时都会发生这种情况.同样,这是针对缓存的元数据运行的,但它始终是完成的.
唯一没有进行此处理的是DB正在使用预编译查询,或者缓存了先前的查询.这是使用绑定参数而不是文字SQL的参数."SELECT*FROM TABLE WHERE key = 1"是与"SELECT*FROM TABLE WHERE key =?"不同的查询.并且"1"在通话中受到约束.
数据库严重依赖页面缓存来完成工作.许多现代数据库都小到足以完全适合内存(或者,我应该说,现代内存足够大以适应许多数据库).然后,后端的主要I/O成本是日志记录和页面刷新.
但是,如果您仍在为数据库访问磁盘,则许多系统完成的主要优化是依赖索引中的数据,而不是表本身.
如果你有:
CREATE TABLE customer (
id INTEGER NOT NULL PRIMARY KEY,
name VARCHAR(150) NOT NULL,
city VARCHAR(30),
state VARCHAR(30),
zip VARCHAR(10));
CREATE INDEX k1_customer ON customer(id, name);
Run Code Online (Sandbox Code Playgroud)
然后,如果您执行"SELECT id,name FROM customer WHERE id = 1",则DB很可能会从索引中提取此数据,而不是从表中提取.
为什么?无论如何它都可能使用索引来满足查询(与表扫描相比),即使在where子句中没有使用'name',该索引仍然是查询的最佳选择.
现在,数据库具有满足查询所需的所有数据,因此没有理由自己查看表页面.使用索引会减少磁盘流量,因为索引中的行密度与表中的行密度相比较高.
这是对某些数据库使用的特定优化技术的手工波形解释.许多人有几种优化和调整技术.
最后,SELECT*对于您必须手动输入的动态查询非常有用,我从不将它用于"真实代码".单个列的标识为DB提供了可用于优化查询的更多信息,并使您可以更好地控制代码中的模式更改等.
小智 5
我认为您的问题没有确切的答案,因为您考虑了维护应用程序的性能和便利性。Select column
更具有性能select *
,但是如果您正在开发面向对象系统,那么您会喜欢使用object.properties
并且您可以在应用程序的任何部分中需要一个属性,那么您将需要编写更多方法来在特殊情况下获取属性,如果您不这样做使用select *
并填充所有属性。您的应用程序需要具有良好的性能select *
,在某些情况下,您需要使用选择列来提高性能。然后,您将拥有两个世界中更好的一个,即在需要性能时编写和维护应用程序和性能的工具。
这里接受的答案是错误的。当另一个问题作为此问题的副本被关闭时,我遇到了这个问题(虽然我仍在写我的答案 - grr - 因此下面的 SQL 引用了另一个问题)。
您应该始终使用 SELECT 属性、属性.... NOT SELECT *
它主要用于性能问题。
SELECT name FROM users WHERE name='John';
不是一个很有用的例子。考虑一下:
SELECT telephone FROM users WHERE name='John';
Run Code Online (Sandbox Code Playgroud)
如果(姓名,电话)上有索引,则无需从表中查找相关值即可解析查询 - 有一个覆盖索引。
此外,假设该表有一个包含用户图片的 BLOB、一个上传的 CV 和一个电子表格……使用 SELECT * 将把所有这些信息拉回 DBMS 缓冲区(强制从缓存中取出其他有用的信息)。然后它将全部发送到客户端,使用网络上的正常运行时间和客户端上的内存用于冗余数据。
如果客户端将数据作为枚举数组(例如 PHP 的 mysql_fetch_array($x, MYSQL_NUM))检索,它也会导致功能问题。也许在编写代码时,'telephone' 是 SELECT * 返回的第三列,但是有人出现并决定在表中添加一个电子邮件地址,位于'telephone'之前。所需字段现在移至第 4 列。
归档时间: |
|
查看次数: |
81434 次 |
最近记录: |