SELECT * 的真相: 索引覆盖(index coverage)
SELECT *的效率很糟糕吗?当然,所有人都知道这一点,但是为什么呢?
是因为返回了太多的数据?
这是一个普遍的回答,但我不这样认为。如果你的数据库设计规范合理,那么带宽占用实际上非常的小。
让我们看看下面的例子。下面的查询将会从AdventureWorks.dbo.TransactionHistoryArchive(总共大约有近9万行数据)中选择出326行数据。第一个使用了SELECT * 查询,后一个查询则有明确的字段。
WHERE ReferenceOrderID < 100
SELECT ReferenceOrderLineID FROM Production.TransactionHistoryArchive
WHERE ReferenceOrderID < 100
在这种情况下,两者在网络带宽的区别只有15K(180K-165K),大约10%的带宽差异。的确值得去优化,但不会有很大的效果。
SELECT * 将造成表/索引扫描
SELECT * 的最大问题是将影响查询计划。SQL Server主要使用索引去查询你需要的数据,当索引包括所有的你请求查询的字段,SQL Server将不需要去在表中查询。这个概念称做索引覆盖。在上面的例子中,第一个查询结果是在聚集索引扫描中,反过来,第二个例子使用了更多更有效率的索引扫描。在这个案例中,索引扫描比聚集索引扫描快100倍。
除非你已经将为每个字段建立了索引(显然不是个好主意),SELECT *是不能够利用到索引覆盖,你只能去做扫描操作(非常的没有效率)。
如果你只是查询你所需要的字段,那你更可能的覆盖到你的索引。我想这就是不推荐使用SELECT *的主要的原因。
稳定性方面
在维护一个应用程序时,SELECT *也会带来一些意想不大的问题。它会引起你的代码发生一些不确定性。如果你增加了一个行(译注:我觉得这里应该是字段)到一个表中,那么SELECT * 返回的结果到你的应用程序中将会在结构上发生变化。良好的应用程序应该是使用字段名称的,而不应该受此影响。当外界发生变化时,良好的应用程序设计也应该最小化的更改。
英文原稿: http://weblogs.asp.net/jgalloway/archive/2007/07/18/the-real-reason-select-queries-are-bad-index-coverage.aspx
posted on 2007-07-20 00:25 Goodspeed 阅读(11294) 评论(38) 编辑 收藏 举报