简体   繁体   English

如何改进MySQL中的Limit子句

[英]How to improve Limit clause in MySQL

I have the posts table with 10k rows and I want to create pagination by that. 我有10k行的posts表,我想通过它创建分页。 So I have the next query for that purpose: 所以我为此目的进行了下一个查询:

SELECT post_id
    FROM posts
    LIMIT 0, 10;

When I Explain that query I get the next result: 当我Explain该查询时,我得到了下一个结果:

在此输入图像描述

So I don't understand why MySql need to iterate thru 9976 rows for finding the 10 first rows? 所以我不明白为什么MySql需要通过9976行迭代才能找到10个第一行? I will be very thankful if somebody help me to optimize this query. 如果有人帮我优化这个查询,我将非常感激。

Also I know about that topic MySQL ORDER BY / LIMIT performance: late row lookups , but the problem still exist even if I modify the query to the next one: 我也知道MySQL ORDER BY / LIMIT性能的主题:后期行查找 ,但即使我将查询修改为下一个查询,问题仍然存在:

SELECT  t.post_id
FROM    (
        SELECT  post_id
        FROM    posts
        ORDER BY
                post_id
        LIMIT 0, 10
        ) q 
JOIN    posts t 
ON      q.post_id = t.post_id

在此输入图像描述

Update 更新

@pala_'s solution works great for above simple case but now while I am testing a more complex query with inner join . @ pala_的解决方案适用于上述简单案例,但现在我正在使用inner join联接测试更复杂的查询。 My purpose is to join comment table with post table and unfortunately when I Explain new query is still iterate through 9976 rows. 我的目的是将评论表与帖子表联系起来,不幸的是,当我解释新查询仍在迭代9976行时。

Select comm.comment_id 
from comments as comm 
    inner join (
        SELECT post_id 
        FROM posts 
        ORDER BY post_id 
        LIMIT 0, 10
    ) as paged_post on comm.post_id = paged_post.post_id;  

Do you have some idea what is the reason of such MySQL behavior ? 你知道这种MySQL行为的原因是什么吗?

Try this: 试试这个:

SELECT post_id
    FROM posts
    ORDER BY post_id DESC
    LIMIT 0, 10;

Pagination via LIMIT doesn't make much sense without ordering anyway, and it should fix your problem. 如果没有订购,通过LIMIT分页没有多大意义,它应该解决你的问题。

mysql> explain select * from foo;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | foo   | index | NULL          | PRIMARY | 4       | NULL |   20 | Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from foo limit 0, 10;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | foo   | index | NULL          | PRIMARY | 4       | NULL |   20 | Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)

mysql> explain select * from foo order by id desc limit 0, 10;
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
|  1 | SIMPLE      | foo   | index | NULL          | PRIMARY | 4       | NULL |   10 | Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)

Regarding your last comments about the comment join. 关于你对评论加入的最后评论。 Do you have an index on comment(post_id) ? 你有comment(post_id)索引comment(post_id)吗? with my test data I'm getting the following results: 用我的测试数据我得到以下结果:

mysql> alter table comments add index pi (post_id);
Query OK, 0 rows affected (0.15 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select c.id from  comments c inner join (select id from posts o order by id  limit 0, 10) p on c.post_id = p.id;
+----+-------------+------------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+------------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL |   10 |                          |
|  1 | PRIMARY     | c          | ref   | pi            | pi      | 5       | p.id |    4 | Using where; Using index |
|  2 | DERIVED     | o          | index | NULL          | PRIMARY | 4       | NULL |   10 | Using index              |
+----+-------------+------------+-------+---------------+---------+---------+------+------+--------------------------+

and for table size reference: 并为表大小参考:

mysql> select count(*) from posts;
+----------+
| count(*) |
+----------+
|    15021 |
+----------+
1 row in set (0.01 sec)

mysql> select count(*) from comments;
+----------+
| count(*) |
+----------+
|     1000 |
+----------+
1 row in set (0.00 sec)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM