文档结构  
翻译进度:已翻译     翻译赏金:0 元 (?)    ¥ 我要打赏

我看到大量的文章都在说 SELECT * 这样的 SQL 语句对性能有多大影响,持有这种观点的人建议我们将需要读取的列都罗列出来而不是使用 SELECT * 的语句用于提升 SQL 执行的性能。今天我就想较真一次,来测试这两者到底有何区别,因为我觉得这个结论有点扯淡。

开始测试

我有如下两个 SQL 查询语句:

SELECT *
FROM Warehouse.StockItemTransactions AS sit;

--and

SELECT sit.StockItemTransactionID,
       sit.StockItemID,
       sit.TransactionTypeID,
       sit.CustomerID,
       sit.InvoiceID,
       sit.SupplierID,
       sit.PurchaseOrderID,
       sit.TransactionOccurredWhen,
       sit.Quantity,
       sit.LastEditedBy,
       sit.LastEditedWhen
FROM Warehouse.StockItemTransactions AS sit;
第 1 段(可获 0.63 积分)

我使用 PowerShell 来运行这些查询几百次,然后通过扩展事件来捕获执行结果,接着对这些结果进行统计和比较。

测试结果

为了了确保测试准确,我执行了很多次的测试过程。有趣的是我在结果中看到了一些差异。其中一个测试只测试单个方法的偏差,而另外一个则相反。因此我们对这些结果取平均值,就会看到如下的结果:

*167.247ms
字段列表165.500ms

这个结果是在每个查询独立执行了 2000 次后的结果,也就是说两个查询在执行 2000 次后会有 2 毫秒的性能偏差,字段列表的查询方式略优。你也可以说二者的性能差别不到 1% 。所以还值得为这不同的写法费心吗,我相信不管做多少测试,这个结果也将会是正确的。在我的多个测试中 SELECT * 语句跑得要更快一些些,我觉得自己有责任提供这个完整的结果,有一些改进,但是我并未此感到兴奋,因为还有数据读取、执行计划等等影响性能的因素。

第 2 段(可获 2.16 积分)

SELECT * 结论

别让我犯错误,有很多不要使用 SELECT * 查询的原因,性能是其中一个因素。但是这么多人认为使用 SELECT * 查询会导致性能低下的结论并不一定是对的。他们只是认为你应该根据需要来读取数据,而不是全部。但我并不认为那些有经验和学识的人建议的那样,使用完整的字段列表代替SELECT * 会使查询变得更快。在上面的测试中我们已经看到了,不是吗?(或许这样说更贴切一点:差别微乎其微,可以忽略不计)

第 3 段(可获 1.36 积分)

文章评论

CY2
我也是这种结论,所以我喜欢用 SELECT * ,因为这样的 SQL 语句看起来很短,而且当表结构有变化的时候,语句不需要跟着改
郑州访客
如果说我只想要某个字段呢?
泉州访客
如果某个字段内容特别大,刚好这个查询又不需要这个字段你试试
广州访客
你试试再下结论
福州访客
当字段有clob或blob等大数据的时候试一下 这个实验的结论有点草率
访客
人家说的本来就是全部字段查询
马鞍山访客
看懂再说话
南昌访客
相同的sql在mysql中存在缓存机制,或计划缓存即上次已经对语法,用法进行了检验,再一次执行,则不会再次进行检验,还有一个mysql自动的优化过程如果是相同的sql这一步也会省略,你查出来的数据,如果是非索引,这些也会有影响的,,影响的因素挺多的
访客
这个结论应该是针对“select 全字段”和“select * ”的比较。“select 部分字段”跟“select * ”没有比较的意义
广州访客
字段多了,sql不影响,但是应用里面要把对象返回到客户端,时间就长了
宜昌访客
对,传输的时间比较长
广州访客
请问你数据量有多大,是否并发了
深圳访客
数据量少差别不大,数据量大了就很明显了。Low的结论是不会有区别的
厦门访客
对,把没必要取出来,会占用内存,所以这个楼主还以为自己多高明回复 @泉州访客 的 #24397# 评论

杭州访客
mysql查询内容前,都要向主机申请所查询字段所设置的长度大小的内存,一个varchar和一个text类型占用的内存自己想想,多一个text你也想想!
南京访客
当数据库和程序不在一个机器上时,肯定会产生时间上的影响,毕竟数据包大了
西安访客
这文章作者是个纸张啊
福州访客
很片面,作者的研究水平有待提高
访客
你最好试过了再回复回复 @广州访客 的 #24404# 评论

南京访客
我没听谁说不用select *是因为这两者的性能差距的。。。大家说的不用主要是考虑的以下几点:
1、select *会导致网络资源大量浪费(服务器和数据库不在一个局域网中时特别明显),程序响应速度急剧下降。
2、如果表结构发生改变,程序可能无法感知(也就是可能不报异常,但逻辑上确是错误的),这可能会导致严重的业务灾难!
淄博访客
你说的还是靠谱的。这个作者太LOW
访客
这个说法不错
深圳访客
这个,你如果一张表有20+个字段,30w+,150M的数据,你查*和其中的某2-3个字段,差距就会很明显,一次就是几毫秒甚至几十毫秒
访客
如果查询出用 而且是没用索引的字段 让后数据量还大 楼主童鞋 就不会这么得出结论了
长沙访客
你都是同一句语句,说不定数据库早就缓存了
访客
1.你测试显然用传统数据库,建议试下列式数据库
2.列只有11个,某些大表有几十个列。
长沙访客
楼主很骚,需要人干
深圳访客
呵呵。。。
访客
这个结论是有点扯,但楼主的测试就呵呵了。首先,楼主没有说明表的量级,其实看楼主没有where条件就知道量级很小。其次,select * 是否影响快慢主要看where条件,以及所选的db种类、存储引擎、索引。而select 字段比select *快这个结论虽不是放之四海兼准,但不论是何种情况select 字段总优于等于select *的效果。
淄博访客
不要不懂装懂。SELECT * 和 SELECT 全部列名不会有什么差别。因为解释是一样的。这厮说的是这种全部罗列的情况并不是不分字段和* 来比较。我也说你能以这个为题目写一篇文章说明你也就顶多是个1-2年的开发者。太浮躁。
访客
人家研究的是select * 和 select 全部字段名的差距,你们非要咬住select * 比select id慢作为抨击点。。。
访客
有这样 查询全部字段 不用 * 而是罗列出来的脑残么 我太害怕了
访客
确实,表的数量级大的话差异还是比较明显的
咸阳访客
如果有几个blog字段的话,select * 和select id就会非常明显
南阳访客
这种文章还有什么翻译的必要? 脱离实际应用场合谈性能都是瞎扯淡。没有数据集大小,没有业务场景模拟, 单独一个简单查询跑2000次有个毛意义
长沙访客
完全是不负责任的帖子,Select * 和Select 字段名称 你就搞不到10个字段的测试,你结合大内容和上100个字段,在加上数据量上100W级行,再结合网络传输来下结论再说
南京访客
select * 本来就对性能没啥影响,但是对代码稳定性影响很大,依赖表结构的字段顺序,字段顺序变了。你的代码就埋个地雷,而且不好查。
长春访客
我的一贯做法 用什么查什么
南充访客
当io成为瓶颈的情况,你试试*会有什么后果
访客
字段多的时候呢!一次性要求数据多的时候呢, 你把DateTable 转成JSON的时候呢?
苏州访客
mysql select 主键 和select * 大数据下差距巨大.
广州访客
如果只是小字段的,差别体现不出来;如果表内有大字段,查询就有所差距,大字段的又不是必须查出来的,就可以通过写详细要查询的内容,撇开对大字段的查询
广州访客
例如这些类型的字段:text、blob
访客
你在你表里的字段里面放一张内容表 你试试 让后数据里面有50万以上数据你在试试 你把不是索引但又不需要的字段查出来 你试试 几千 哪怕几万条数据 都 没有差距 如果访问量大 数据又多的情况下你试试
访客
楼主没有遇到过大数据 鉴定完毕
郑州访客
你这个只是单表查询,如果是多表联合查询呢?数据量非常大的情况你怎么不考虑呢,你这个结论非常差劲啊!
深圳访客
作者大傻逼,select * 能用上覆盖索引? 网络传输越大越快?? 你tm在逗我!!
崇左访客
楼主,你想得太简单了。估计你是没经历过一条查询语句需要跑几个小时的场面
厦门访客
如果字段特别多(150个以上),但是需要显示的字段特别少(3-5)时,差异就比较大了。笔者这个分析没有啥意义,谁都知道。
访客
我相信不管做多少测试,这个结果也将会是正确的。在我的多个测试中 SELECT * 语句跑得要更快一些些,我觉得自己有责任提供这个完整的结果,有一些改进,但是我并未此感到兴奋,因为还有数据读取、执行计划等等影响性能的因素。
我相信。。。我觉得。。。我xxx。。。。。

2000次的测试也算测试...
访客
楼主也忘记了,数据库对sql是有调优以及缓存的。。这个测试不靠谱。。
访客
不同数据库的处理方式不同。。。。
杭州访客
写这么一个文章,这不是找喷么?就这样就能测出一个结论了?
郑州访客
想多了吧?谁说select *慢了?我没见过有人说慢啊,你一次听作者这么说
访客
暂且不说性能,因为我也觉得这跟sql执行效率关系不是很大。但为什么要使用字段?原因我知道的有2:
1.传输大小
2.缓存大小
访客
应该需要这种较真的人和较真的方法
访客
这个测试没有意义,他说的前提是全部列和*的区别,正常开发中几乎不会出现
太原访客
日 试好了 再说
访客
当你用过如sap、siebel之类的产品表的时候,你再来告诉我*和指定字段无差别
深圳访客
你这个测试样本有问题,会误导人的。如果 select 字段都有索引,查询的时候只会做索引扫描不会做全表扫描。同时查询字段数量不一样的时候,把数据传输给客户端也是有时间差的,当然一般本机到本机无所谓。

如果真要做试验,加一个 select pk, 和 select *,在千万级的数据表上对比下。
访客
着实略浮躁啊,这种结论有什么意义?
访客
测试范围太小,结论不予采用
南京访客
楼主只是说在要取完整的字段的情况下,SELECT *和全字段罗列性能没差,有些人看清楚再评论好么;
楼主说的对,楼主万岁
访客
这样就算完了?你表里面几百万数据的时候呢?
广州访客
就算是要取全部,也建议全部写上字段名,你用*的话,数据库系统会先去字典表中查出所有的字段名称,会多一次内部字典表的查询。
佛山访客
我就看看不说话
佛山访客
其实我不在佛山
佛山访客
我在珠海呢
访客
对于你这篇文章只能说你是个小白啊
1:单从数据库查询执行效率两者没有差别
2:建议不使用*的原因是因为如果字段多的情况下,数据的传输量会增加,传输需要带宽和时间,遇到网络不好,数据量大你就跪了
访客
看投影字段吧 ,不严谨
杭州访客
首先select * 最起码需要多查询一次表字段,其二多余的数据占内存,其三若存在联合索引多余的字段可能会使索引失效,其四若多余的数据是大数据数据会向硬盘取造成硬盘开销增加。最好现在网站瓶颈在于数据库,能省则省。