为什么select * from不是好的选择?
在这里只是针对innodb数据库引擎来说明。我每次看到select * from tableName时,我都觉得有没有必要?取出全部的列会让优化器无法完成索引覆盖扫描这类优化,还会为服务器带来额外的I/O、内存和CPU的消耗。
这里重点说一点,当一个表中有varchar或者varbinary、各种text类型、各种BLOB类型时,在数据库存储这些大容量的字符串内容,BLOB和TEXT都是为存储很大的数据而设计的字符串数据类型,分别采用二进制和字符方式存储。MySQL把每个BLOB和TEXT值当作一个独立的对象处理。存储引擎 在存储时通常会做特殊处理。当BLOB和TEXT值太大时,InnoDB会使用专门前“外部”存储区域来进行存储,此时每个值在行内需要存储一个指针,然后在外部 存储区域存储实际的值。
这样导致select * from 的时候包含这些大字段值,产生查找到外部存储器地址,又进行一次或者多次的外部I/O查询,速度会非常的慢。
下面细讲一下mysql存储原理:
innodb中磁盘和内存交互的基本单位都是页,也就是说Innodb是以页为基本单位来管理存储空间的,我们记录都会被分配到某个页中存储。而一个页大小是16KB,也就是16384字节。在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,或者一次最少把内存中的16KB内容刷新到磁盘中。当一个列的实际数据就需要超过16KB时,很显然一个页存不下一条记录。问题怎么解决呢?
在compact行格式和dynamic行格式中,对于占用存储空间非常多的列,对于compact格式,存储该列的一部分数据,然后在真实数据处用20字节存储指向这些页的地址(需要到外部存储页其余数据)。而dynamic格式,在记录真实数据时,该列只会用20字节空间,而这20字节的空间不存储数据,因为数据都分散存储在其他几行中了。这20字节的空间存储的是分散行的地址和占用的字节数。分散行记录是单链表连接的结构。注意compact和dynamic有区别
compact的行格式存储方式
从上图看到,compact行格式,如果某一列的数据非常多,则在本记录的真实数据处只会存储该列前768字节的数据以及只想其他页面的地址(20字节),除了768字节之外的数据的页面称为溢出页。如下图