读一读

  1. 表非常大以至于无法全部都放在内存中,或者只有在表的最后部分有热点数据,其他均是历史数据。

  2. 分区表的数据更容易维护。想删除大量数据可以直接清除整个分区。另外,还可以对一个独立分区进行优化,检查,修复等操作。

  3. 分区表的数据可以分布在不同的物理设备上,从而高效地利用多个硬件设备。

  4. 可以使用分区表来避免某些特殊的瓶颈,例如InnoDB的单个索引的互斥访问,ext3文件系统的inode锁竞争等。

  5. 如果需要,还可以备份和恢复独立的分区,这在非常大的数据集的场景下效果非常好。


最好的当然就是使用B-Tree的索引啦!如果没办法使用索引,他就会使用临时表或者文件排序来做分组。如果需要对关联查询做分组(GROUP BY),并且是按照查找表中的某个列进行分组,那么通常采用查找表的标识列分组的效率会比其他列更高。


子查询最好的优化就是尽可能使用关联查询替代。如果使用的是Mysql5.6或更新的版本或则MariaDB,那么就可以直接忽略关于子查询的这些建议了。


  1. 确保ON或者USING子句中的列上有索引。在创建索引的时候就要考虑到关联的顺序,一般来说,除非有其他理由,否则需要在关联顺序中的第二个表的相应列上创建索引。

  2. 确保任何的GROUP BY和ORDER BY中的表达式只涉及到一个表的列,这样MYSQL才有可能使用索引来优化这个过程。


COUNT()查询一般来说会需要扫描大量的行才能获得精确的结果,很难优化,除了没有WHERE条件的MyISAM表,MYSQL会直接利用存储引擎的特性直接获取得到这个值。如果要优化,只能用个近似值了,降低查询频率,缓存值,近似认为这个值就是下次更新前的总数。


对于UNION查询,MySQL先将一系列的单个查询结果放到一个临时表中,然后在重新读取临时表数据来完成UNION查询。在MySQL的概念中,每个查询都是一次关联,所以读取结果临时表也是一次关联。MySQL先在一个表中循环取出单条数据,然后再嵌套循环到下一个表中寻找匹配的行,一次下去,直到找到所有表中匹配的行为止。然后根据各个表匹配的行,返回查询中需要的各个列。


很多高性能的应用都会对关联查询进行分解。简单地,可以对每一个表进行一次单表查询,然后将结果在应用程序中进行关联。

可以让缓存更高效,关联查询时,只要一个表发生了细微变化,那么缓存就会无效了。执行单个查询可以减少锁的竞争。


有时候对于一个大查询我们需要“分而治之”,将大查询切分成小查询,每个查询功能完全一样,只完成一小部分,每次只返回一小部分查询结果。例如删除旧数据,定期地清理大量数据时,如果同一个大的语句一次完成的话,则可能需要一次锁住很多数据,占满整个事务日志,耗尽系统资源,阻塞很多小的但重要的查询。


如果查询需要扫描大量的数据但只返回少数的行:

  1. 使用索引覆盖扫描,把所有需要用的列都放到索引中,这样存储引擎无须回表获取对应行就可以返回结果了。

  2. 改变库表结构。例如使用单独的汇总表。

  3. 重写这个复杂的查询,让MySQL优化器能够以更优化的方式执行这个查询。


通常来说,查询的生命周期大致可以按照顺序来看:从客户端,到服务器,然后在服务器上进行解析,生成执行计划,执行,并返回结果给客户端。其中“执行”可以认为是整个生命周期中最重要的阶段,这其中包括了大量为了检索数据到存储引擎的调用以及调用后的数据处理,包括排序分组等。