select * from table where status = xx limit 10 offset 100000;
ページングシーンの下では、インデックスがあっても、要求は、スタンドアローンのみ10万例2~3秒程度のデータ量で、非常に遅くなります制限
分析
指数
私たちは、MySQLのインデックスがあることを知っているB +ツリー。それは、バイナリツリーの場合、彼らは木の分布のトップ100の数を知ることができないので、私はバイナリの特性を使用することはできませんので、探しています。B +ツリーにおいて、リーフノードは順に一覧表示することができるO(n)
100の多数が、それでもO(n)を見つけるために、複雑さの、またそう遅い他の理由があるかどうかの
、InnoDBののインデックスは2つに分割されている情報へのアクセスによる(著)
- クラスタ化インデックス:主キーインデックスと対応する実際のデータ、索引リーフ・ノードは、データ・ノード、データを見つけるインデックスを見つけるです
- セカンダリインデックスは:リーフ・ノードまたは主キーのIDが含まれているインデックス・ノードである2つのノードとして理解することができ、また、あなたは再びデータを照会する必要があります
旧100,000捨てされる場合でも、MySQLのの層化に、MySQLは、セカンダリインデックスの主キーのIDも越えると、クラスタ化インデックスのデータをチェックします、これは自然にゆっくりとハスキーへ100000ランダムIOです
層状
あなたはこの、論理演算子について前の概念を理解する必要があります。論理的なクエリプラン演算子のいくつかを簡単に見て
- データソース:データソース私たちのSQL文のテーブルです。
select name from table1
TABLE1 - 参加:接続を、として
select * from table1 table2 where table1.name = table2.name
、2つのテーブルが参加んです。参加条件は、最も簡単な同等の接続は、もちろん、我々は他の存在を知っているinner join
、left join
、right join
など - 選択:選択して、
select name from table1 where id = 1
フィルタ場所の条件 - 集計:グループ化、等の
select sum(score) from table1 group by name
基による。パケット、重合操作に応じて、いくつかの列は、MAX、MIN、合計、カウントなど、パケット数後に行ってもよい平均等 - Projection:投影,指搜索的列,如
select name from table1 where id = 1
中的列name - Sort:排序,如
select * from table1 order by id
里面的order by。无序的数据通过这个算子处理后,输出有序的数据 - Apply:子查询,如
select * from (select id,name from table1) as t
中的(select id,name from table1) as t
。可以进行嵌套查询。
选择、投影、连接就是最基本的算子,其中 Join 有内连接,左外右外连接等多种连接方式
select b from t1, t2 where t1.c = t2.c and t1.a > 5
变成逻辑查询计划之后
- t1 t2 对应的 DataSource,负责将数据捞上来
- 上面接个 Join 算子,将两个表的结果按 t1.c = t2.c连接
- 再按 t1.a > 5 做一个 Selection 过滤
- 最后将 b 列投影
下图是未经优化的表示,所以说不是mysql不想把limit传递给引擎层,而是因为划分了逻辑算子,所以导致无法直到具体算子包含了多少符合条件的数据
ps:SELECT执行顺序
SQL语句执行顺序 | MySQL执行顺序 | |
---|---|---|
1 | select distinct | from |
2 | from | on |
3 | join | join |
4 | on | where |
5 | where | group by |
6 | group by | having+聚合函数 |
7 | having | select distinct |
8 | union | union |
9 | order by | order by |
10 | limit | limit |
解决方法
解决方法有2种
- 根据业务实际需求,看能否替换为下一页,上一页的功能,特别在移动端。把limit替换成
>id
的方式。该id再调用时,需要返回给前端。但是这种有些业务场景不适用
select * from table where status = xx id > 100000 limit 10;
- 【推荐】嵌套子查询,先查找数据的主键值,因为主键在辅助索引上就有,所以不用回归到聚簇索引的磁盘去拉取。再通过这些已经被limit出来的10个主键id,去查询聚簇索引。这样只会十次随机IO。在业务确实需要用分页的情况下,使用该方案可以大幅度提高性能。通常能满足性能要求
select xxx from in (select id from table where status = xx limit 10 offset 100000);
原文出处,删除作者经历和感想部分,如原作者觉得此文不妥,我会修改
作者:叶不闻
链接:https://juejin.im/post/5c4db295e51d4503834d9c43
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
逻辑算子部分引用了
作者:叁金
链接:http://www.imooc.com/article/278660
来源:慕课网