原因
-
查詢所有列導致回表 。
-
limit a, b會查詢前a+b條數據,然后丟棄前a條數據
優化方案
兩種,一般用覆蓋索引,使用條件過濾有前提限制。
1. 覆蓋索引
所謂的覆蓋索引就是從非主聚簇索引中就能查到的想要數據,而不需要通過回表從主鍵索引中查詢其他列,能夠顯著提升性能。
優化方案就是先查詢得到主鍵id,然后再根據主鍵id查詢其他列數據.
select * from user a join (select id from user where sex = 1 limit 10000000,10) b on a.id = b.id;
上面內容也許有點抽象,解釋一下,因為 sex 是有索引,這里命中 sex 索引,而其 data 存儲的是 主鍵值(即 id)那么可以直接得到,所以無需再回表。
回表: 如果查詢不是 id 或者 sex ,而是其他字段,那么還要走一遍主索引(即 id 的 B+ 樹),得到這個字段的數據。這就是回表。
詳細可以看:mysql覆蓋索引與回表
關於什么是 非聚簇索引 和 聚簇索引看:MySQL 之 非聚簇索引 和 聚簇索引
2. 條件過濾
基於排序做條件過濾,這樣的方式優化是有條件的:主鍵 id 必須是有序的。在有序的條件下,也可以使用比如創建時間等其他字段來代替主鍵 id ,但是前提是這個字段是建立了索引的。
一般使用自增主鍵的時候可以使用這個方式
select * from user where sex = 1 and id > (select id from user where sex = 1 limit 10000000, 1) limit 10;