我有以下查询:
explain select * from users, dls where dls.user_id=users.id and users.status = 'accepted' and users.acc = 0 order by users.user_name desc limit 18416, 16
导致以下解释;
+----+-------------+-------+------+------------------------+-------------+---------+---------------------------------+-------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+------------------------+-------------+---------+---------------------------------+-------+---------------------------------+
| 1 | SIMPLE | dls | ALL | PRIMARY,user_id | NULL | NULL | NULL | 19910 | Using temporary; Using filesort |
| 1 | SIMPLE | users | ref | PRIMARY,id_user_name | id_user_name | 4 | dls.user_id | 1 | Using where |
+----+-------------+-------+------+------------------------+-------------+---------+---------------------------------+-------+---------------------------------+
2 rows in set (0.00 sec)
这个查询非常非常慢,我无法弄清楚如何修复它。我尝试了各种索引,阅读有关如何通过/限制查询优化顺序的文章,但结果保持不变。有人可以帮忙吗?
编辑:架构:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL auto_increment,
`user_name` varchar(100) character set utf8 NOT NULL,
`status` enum('accepted','rejected') character set utf8 NOT NULL,
`acc` varchar(6) character set utf8 NOT NULL,
PRIMARY KEY (`id`),
KEY `user_name` (`user_name`),
KEY `id_user_name` (`id`,`user_name`)
)
CREATE TABLE `dls` (
`user_id` int(10) unsigned NOT NULL,
`category_id` bigint(20) NOT NULL,
`download_url` varchar(255) character set utf8 NOT NULL,
PRIMARY KEY (`user_id`,`category_id`),
KEY `user_id` (`user_id`)
)
Scrummeister的查询输出;
+----+-------------+-------+------+------------------------+--------+---------+------------------------------+-------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+------------------------+--------+---------+------------------------------+-------+-----------------------------+
| 1 | SIMPLE | u | ALL | PRIMARY,id_user_name | NULL | NULL | NULL | 10838 | Using where; Using filesort |
| 1 | SIMPLE | dls | ref | PRIMARY,user_id | user_id | 4 | u.id | 2 | |
+----+-------------+-------+------+------------------------+--------+---------+------------------------------+-------+-----------------------------+
答案 0 :(得分:3)
已知MySql使用大偏移量LIMIT
存在问题。
STRAIGHT_JOIN
关键字告诉MySql首先扫描users表,然后为每个用户查找dls
表中的行。
SELECT STRAIGHT_JOIN *
FROM users u JOIN dls ON dls.user_id = users.id
WHERE u.status = 'accepted' and u.acc = 0
ORDER BY users.user_name desc
LIMIT 18416, 16
除非需要使用STRAIGHT_JOIN,否则不建议使用STRAIGHT_JOIN。在这种特定情况下,我认为它可能有效,因为它可以使用user_name
索引进行排序。
您有其他选择:
sort_buffer_size
read_rnd_buffer_size
的尺寸(小心!)users
表格上进行分页,无论他有多少dls
,只应用JOIN
。WHERE user_name > "{LastPageLastUsername} LIMIT 0,16"
,则会增加要进行其他优化,请阅读ORDER BY Optimization和Limit Optimization
答案 1 :(得分:0)
尝试使用以下列
向users表添加索引status, acc, user_name
或
acc, status, user_name
哪个更快