2015-04-15 43 views
3

我有posts表中有10k行,我想通過它創建分頁。所以,我對於這一目的的一個查詢:如何提高MySQL中的限制條款

SELECT post_id 
    FROM posts 
    LIMIT 0, 10; 

當我Explain該查詢,我得到了一個結果:

enter image description here

所以我不明白爲什麼MySQL的需要遍歷通9976用於查找10個第一行的行?如果有人幫助我優化此查詢,我將非常感激。

我也知道這話題MySQL ORDER BY/LIMIT performance: late row lookups,但即使我修改查詢到下一個問題仍然存在:

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 

enter image description here

更新

@ pala_的解決方案適用於上述簡單情況,但現在正在測試更復雜的查詢時使用inner join。我的目的是加入評論表和帖子表,不幸的是,當我解釋新的查詢仍然遍歷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; 

你有一些想法是什麼原因導致這種MySQL行爲?

+0

爲什麼你需要一個衍生零件並加入爲什麼不只是一個查詢與'選擇..limit ' –

+2

多數民衆贊成他的第一個查詢,他的比較 –

回答

5

試試這個:

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

分頁通過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) 

關於您最近對評論加入的評論。你有comment(post_id)的索引嗎?我的測試數據,我發現了以下結果:

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    | 
+----+-------------+------------+-------+---------------+---------+---------+------+------+--------------------------+ 

和檯面尺寸參考:

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) 
+0

謝謝你的答案!它運作良好。但我還有一個問題。現在我正在用內連接測試更復雜的查詢。我的目的是加入評論表與帖子表,不幸的是,當我解釋新的查詢仍然迭代到9976行。 <<< 從評論作爲COMM選擇 \t \t comm.comment_id 內加入 (SELECT POST_ID 來自帖子 ORDER BY POST_ID LIMIT 0,10)上comm.post_id = paged_post.post_id作爲paged_post ; >>> 你有一些想法,這種MySQL行爲的原因是什麼? – Speise

+0

嘗試在沒有子查詢的情況下執行此操作,並將限制添加到查詢的末尾,即'解釋select * from posts p內部連接註釋c on p.post_id = c.post_id order by p.post_id desc limit 0,10 ' –

+0

我使用子查詢進行分頁分頁。如果我刪除子查詢並像上面提到的那樣只使用連接,那麼分頁將會中斷,並且我將從連接的表中獲取第一行。有沒有其他方法可以通過郵寄來實現分頁結果? – Speise