我的数据库mysql
中有一千条记录,我使用分页来检索10个结果。
当我在查询中添加order by
时,它会变慢,但当我省略它时,查询运行得非常快。
我知道问题来自于查询加载整个结果,对它们进行排序,然后获得10条记录。
我不使用索引,因为用于订单的列是PK,我认为如果我在mysql
中没有错误,则会在每个主键上自动创建索引
我的SQL查询
select distinct ...... order by appeloffre0_.ID_APPEL_OFFRE desc limit 10
和我的索引
mysql> show index from appel_offre;
+-------------+------------+--------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------------+------------+--------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| appel_offre | 0 | PRIMARY | 1 | ID_APPEL_OFFRE | A | 13691 | NULL | NULL | | BTREE | | |
| appel_offre | 1 | appel_offre_ibfk_1 | 1 | ID_APPEL_OFFRE_MERE | A | 2 | NULL | NULL | YES | BTREE | | |
| appel_offre | 1 | appel_offre_ibfk_2 | 1 | ID_ACHETEUR | A | 2 | NULL | NULL | | BTREE | | |
| appel_offre | 1 | appel_offre_ibfk_3 | 1 | USER_SAISIE | A | 2 | NULL | NULL | YES | BTREE | | |
| appel_offre | 1 | appel_offre_ibfk_4 | 1 | USER_VALIDATION | A | 4 | NULL | NULL | YES | BTREE | | |
| appel_offre | 1 | ao_fk_3 | 1 | TYPE_MARCHE | A | 2 | NULL | NULL | YES | BTREE | | |
| appel_offre | 1 | ao_fk_5 | 1 | USER_CONTROLE | A | 2 | NULL | NULL | YES | BTREE | | |
+-------------+------------+--------------------+--------------+---------------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
7 rows in set (0.03 sec)
在explain cmd中没有选择索引:
+----+-------------+---------------+--------+-------------------------------------+--------------------+---------+----------------
| id | select_type | table | type | possible_keys | key | key_len | ref
+----+-------------+---------------+--------+-------------------------------------+--------------------+---------+----------------
| 1 | SIMPLE | appeloffre0_ | ALL | NULL | NULL | NULL | NULL
更新解决方案
问题来自distinct
,当我删除它时,查询最终使用索引。
答案 0 :(得分:3)
因为你已经在“USER_VALIDATION”上使用索引,所以MySQL不会使用ID索引。
尝试重建USER_VALIDATION索引以包含ID:
CREATE UNIQUE INDEX appel_offre_ibfk_4 ON appel_offre (USER_VALIDATION, ID);
记录所有Hibernate查询,解压慢查询并在db控制台中使用EXPLAIN来了解MySQL为此查询选择的执行计划。即使有索引,db也可能使用FULL TABLE SCAN,因为索引太大而无法容纳到内存中。尝试按照in this post所述给它一个提示。
根据MySQL ORDER BY optimization documentation你应该:
要提高ORDER BY速度,请检查是否可以让MySQL使用索引而不是额外的排序阶段。如果无法做到这一点,您可以尝试以下策略:
•增加sort_buffer_size变量值。
•增加read_rnd_buffer_size变量值。
•通过仅根据需要声明列来减少每行RAM的使用 要保存存储在其中的值。例如,CHAR(16)是 如果值不超过16个字符,则优于CHAR(200)。
•将tmpdir系统变量更改为指向专用文件 具有大量可用空间的系统。变量值可以列出 以循环方式使用的几条路径;你可以用它 功能将负载分散到多个目录中。路径应该是 在Unix和分号字符上用冒号字符(“:”)分隔 (“;”)在Windows,NetWare和OS / 2上。路径应该命名目录 在位于不同物理磁盘上的文件系统中,没有什么不同 同一磁盘上的分区。
同时确保DISTINCT不会否决您的索引。尝试删除它,看看它是否有帮助。
答案 1 :(得分:2)