查询非分区表时,查询优化器可以利用索引进行排序,并根据LIMIT子句限制数据读取。例如,在 a 列上具有单列索引 idx_a 的非分区表 my_table 中,以下
SELECT *
FROM my_table
ORDER BY a DESC
LIMIT 100;
此查询可以从末尾扫描 idx_a 索引,并在读取 100 行后停止,而不管 my_table 中的总行数。
现在,考虑一个按主键分区的分区表 my_partition_table。假设运行相同的查询:
SELECT *
FROM my_partition_table
ORDER BY a DESC
LIMIT 100;
在这种情况下,查询不使用文件排序,正如 EXPLAIN 计划所确认的那样。但是,由于表是按主键分区的,因此列 a 跨越所有分区。
在这种情况下MySQL如何处理排序?具体来说,它如何检索并合并所有分区的数据以高效地生成 a 列的排序结果?
您已经发现
PARTITIONing
(在 MySQL 中)的多种方法之一并不比非分区更好,甚至可能更糟。
按
PRIMARY KEY
进行分区永远(?)比等效的非分区表更好。
通过PK进行分区,然后通过PK查找(点查询或范围查询)就会进行“分区剪枝”。 但这样的剪枝并不比使用 BTree 快。
通过PK分区,然后通过二级索引查找——所有分区都需要查看。 然后,根据其他情况,它可能仍然需要收集和排序找到的行。 (我怀疑它是否足够智能来合并;我没有听说它会并行进行分区。)
如果
WHERE
子句需要二维索引,分区可以提供这样的功能——修剪其中一个维度,然后一个或多个索引查找另一个维度。
一般来说,如果“分区键”是而不是PK或任何其他索引,那么希望获得任何好处的唯一方法。
更多讨论:分区