select * 与 select xxx,xxx 性能问题
SQL
sql 1:
SELECT * FROM TABLE
sql 2:
SELECT column1, colum2, column3, etc. FROM TABLE
为啥说 sql 2 比 sql 1 好一些
- 字段多,不需要多字段会增加数据传输使劲和网络开销。
用 SELECT *
数据库需要解析更多的对象、字段、权限、属性等相关内容,如果 SQL
复杂,硬解码比较多会对数据库造成沉重的负担。
增大网络开销;* 有时会误带上如
log、Icon、MD5`之类的无用且大文本字段,数据传输size会几何增涨。如果DB和应用程序不在同一台机器,这种开销非常明显
即使 mysql
服务器和客户端是在同一台机器上,使用的协议还是 tcp
,通信也是需要额外的时间。
- 对于无用的大字段,如 varchar、blob、text,会增加 io 操作
准确来说,长度超过 728 字节的时候,会先把超出的数据序列化到另外一个地方,因此读取这条记录会增加一次 io 操作。(MySQL InnoDB)
- 如果存在覆盖索引,
select *
走不了“覆盖索引”的策略优化
SELECT *
杜绝了覆盖索引的可能性,而基于MySQL优化器的“覆盖索引”策略又是速度极快,效率极高,业界极为推荐的查询优化方式。
覆盖索引 case1 :
有一种索引,叫做覆盖索引,为了避免回表查询,通常使用覆盖索引。
比如有一个常用查询,只需要用到表中的某两列,user_id
和post_id
,而且有一个多列索引已经覆盖了这两个列,那么这个索引就是这个查询的覆盖索引了。
如果select user_id,post_id from Table
的话,mysql是可以不用读data,直接使用index里面的值就返回结果的.
但是一旦用了select*
,就会有其他列需要读取,这时在读完index以后还需要去读data才会返回结果。这两种处理方式性能差异非常大,特别是返回行数比较多,并且读数据需要IO的时候,可能会有几十上百倍的差异。
查看执行计划 explain 也可以看到, sql 1 这个方式,走索引,Extra信息 内容是 Using index
,select *
内容是是 Using where
。
索引是建的越多越好吗?
-
数据量小的表不需要建立索引,建立会增加额外的索引开销
-
不经常引用的列不要建立索引,因为不常用,即使建立了索引也没有多大意义
-
经常频繁更新的列不要建立索引,因为肯定会影响插入或更新的效率
-
数据重复且分布平均的字段,因此他建立索引就没有太大的效果(例如性别字段,只有男女,不适合建立索引)
-
数据变更需要维护索引,意味着索引越多维护成本越高。
-
更多的索引也需要更多的存储空间
参考资料
- https://stackoverflow.com/questions/65512/which-is-faster-best-select-or-select-column1-colum2-column3-etc
- https://www.modb.pro/db/72277