读一读

  1. 单行访问是很慢的。特别是在机械硬盘存储中。如果服务器从存储中读取一个数据块是为了获取其中一行,那么就浪费了很多工作。最好读取的块中能包含尽可能多所需要的行。使用索引可以创建位置引用以提升效率。

  2. 按顺序访问范围数据是很快的,这有两个原因。第一,顺序I/O不需要多次磁盘寻道,所以比随机I/O要快很多(特别是对机械硬盘)。第二,如果服务器能够按需要顺序读取数据,那么就不再需要额外的排序操作,并且GROUP BY查询也无需再做排序和将行按组进行聚合计算了。

  3. 索引覆盖查询是很快的。如果一个索引包含了查询需要的所有列,那么存储引擎就不需要再回表查找行。这避免了大量的单行访问,单行访问时很慢。


B-Tree索引可能会碎片化,这会降低查询的效率。

  1. 行碎片:这种碎片指的是数据行被存储为多个地方的多个片段。即使查询只从索引访问一行记录,行碎片也会导致性能下降。

  2. 行间碎片:行间碎片是指逻辑上顺序的页,或者行在磁盘上不是顺序存储的。

  3. 剩余空间碎片:剩余空间碎片是指数据页中有大量的空余空间。这会导致服务器读取大量不需要的数据,从而造成浪费。


可以通过执行OPTIMIZE TABLE或者导出再导入来重新整理数据。也可以对那些不支持的使用ALTER TABLE ... ENGINE=当前引擎。


Mysql的查询优化器会通过两个API来了解存储引擎的索引值的分布信息,以决定如何使用索引。第一个API是records_in_range(),通过向存储引擎传入两个边界值获取在这个范围大概有多少条记录(具体引擎不同,InooDB是估算值)。第二个API是info(),该接口返回各种类型的数据,包括索引基数。


如果通过Check Table检查到表发生了错误,可以通过Repair Table来修复损坏的表。可以设置innodb_force_recovery参数进入InnoDB的强制恢复模式来修复数据。


索引会让查询锁定更少的行。InnoDB只有在访问行的时候才会加锁,而索引会减少InnoDB访问的行数。但这个只有在存储引擎层过滤掉相应的数据(where),才可以使用索引减少锁定行。


MySQL允许在相同的列上创建多个索引。

重复索引是指在相同的列上按照相同的顺序创建相同类型的索引。例如:创建一个主键后,先加上惟一限制,再加上索引。事实上这里创建了三个重复的索引,因为唯一限制和主键都是通过索引实现的。

冗余索引就是同而又不同的索引,就是你创建了索引(A,B),然后又创建索引(A)。


聚簇索引并不是一种单独的索引类型,是一种数据的存储方式。当表有聚簇索引时,它的数据行实际存放在索引的叶子页中,数据行和相邻的键值紧凑地存储在一起。数据行不能分散,所以一个表只能有一个聚簇索引。


有时候需要索引很长的字符列,这会让索引变得大且慢。通常可以索引开始的部分字符,这样可以大大节约索引空间,从而提高效率。但这样会降低索引的选择性(不重复的索引/数据表记录数)。所以,诀窍在于要选择足够长的前缀以保证高的选择性和高的效率。前缀的“基数”应该接近与完整列的“基数”。可以对比查询全值出现的次数和查询前缀的出现次数来大概推论出前缀的大小。


就是说索引不能是表达式的一部分,就单单的就是它。

例如:

select * from accountinfo where user_id+1=5;

这样索引是不可以生效的。


索引并不总是最好的工具。对于非常小的表,大部分情况下简单的全表扫描更高效。对于中到大型的表,索引就非常有效了。但对于特大型的表,建立和使用索引的代价将随之增长。这时候使用分表,分区技术更有用,查询的数据单位使用块级别了。