インデックス-06 ORDER BY

TOC


並べ替えを達成するために、まず、

SELECT city,
       name,
       age
FROM t
WHERE city='杭州'
ORDER BY name LIMIT 1000 ;

1.すべてのソートフィールド

1.1注文プロセス

  1. 初期化sort_bufferは、都市、氏名、年齢フィールドに決定します
  2. 最初の都市= '杭州のプライマリキーを検索
  3. からsort_bufferに名前、都市、年齢三つのフィールド、主キーを取って、全体のラインを見つけました
  4. 街からレコードインデックスを削除します
  5. 市は、クエリの値を満たさなくなるまで3〜4を繰り返します
  6. sort_bufferソートデータ名フィールド
  7. クライアント1000に戻って最初の行を取ります

1.2一時ファイル

名前のソートがメモリ内で行うことができるために、それは外部ソートを使用する必要があり、必要なメモリは、ソートsort_buffer_sizeのに依存
スペースは、ソートsort_buffer_size、開かれたことです
。1.ソートデータ量<sort_buffer_size、メモリー内ソート
2.ソートデータ量> sort_buffer_sizeは、メモリが収まらない、ランキングを助ける一時ディスク・ファイルを使用していました

一時ファイルにsort文を使用するかどうかを確認する方法

/* 打开 optimizer_trace,只对本线程有效 */
SET optimizer_trace='enabled=on'; 

/* @a 保存 Innodb_rows_read 的初始值 */
select VARIABLE_VALUE into @a from performance_schema.session_status where variable_name = 'Innodb_rows_read';

/* 执行语句 */
select city, name,age from t where city='杭州' order by name limit 1000; 

/* 查看 OPTIMIZER_TRACE 输出 */
SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G

/* @b 保存 Innodb_rows_read 的当前值 */
select VARIABLE_VALUE into @b from performance_schema.session_status where variable_name = 'Innodb_rows_read';

/* 计算 Innodb_rows_read 差值 */
select @b-@a;

number_of_tmp_filesソートプロセスは、一時ファイルの数が使用されることを示す。
MySQLのデータは、これらの一時ファイルの存在が秩序に、その後、それぞれの後に別々に12が再結合順序これらのファイルが格納されている、12個の部分にソート大きなファイル


2.ソートのROWID

上記のアルゴリズムは、元のテーブルを介して読み出されたデータは、残りの操作はsort_bufferと一時ファイルにある
フィールドが返される必要があるクエリで複数のフィールドに入れsort_buffer、問題、多くの時間があるので、同時にメモリ一時ファイルの数に分割するダウン行比較的少数の、
非常に大きい単一ライン、良好な効率、16 = max_length_for_sort_data設定されたアルゴリズムのパラメータに影響を与える、
行の長さを区分制御パラメータデータ、一行の長さがこの値を超えると、アルゴリズムは変更する必要があります

都市は、名前、年齢は三つのフィールド36の全長であり、16はフィールドのみ名と主キーIDビートシーケンスsort_buffer配置max_length_for_sort_dataに設定されています

プロセス:

  1. 二つのフィールド名、IDに決定初期化sort_buffer、
  2. = '杭州のプライマリキーID都市を満たす市からの最初のインデックスを探します
  3. メインキーからアクセス、名前のIDに,,名前を取るsort_buffer
  4. 街からレコードインデックスを削除します
  5. 3-4を繰り返します
  6. 名前のsort_bufferソート
  7. トラバーサルのソート結果は、バックテーブルにアクセス都市、名前に、1000行の前に撮影した、年齢がクライアントに返さ


二回裏のテーブルへのアクセス、examined_rows 4000の間に、しかし= 5000 @ B- @選択し、アクセス+ 1000のコスト4000
sort_keyにSORT_MODEは、ROWIDの
number_of_tmp_fileは少ないソートフィールドので、10となり


3.比較の概要

MySQLの十分なメモリ、ディスクアクセスを最小限に抑えるためのメモリより使用。
ソートの高コスト、および元のデータをする必要はありませんので、でも、ディスクの並べ替えが発生
tはインデックスcity_user(都市追加テーブル変更 、名前を);
等の設立の場合インデックス、市=「杭州」、名前や整然とした、クエリ処理後:

  1. 市からは、撮影した名前は、最初の都市を満たし= '杭州のプライマリキーID
  2. マスターキーの名前、都市、年齢から撮影
  3. 街のインデックスから削除
  4. 2-3ライン1000の第二の端部への問い合わせまで、繰り返される、または都市を満たしていない=「杭州」

このプロセスは、一時テーブルを必要としない、あなたはソートする必要はありません。


インデックス例第二に、最適化

语句和表结构

## SQL
SELECT *  
FROM t_follow_timeline_099  force index (idx_uid_status)
WHERE UID = 1833901412800099
  AND status = 1
ORDER BY create_time DESC
LIMIT 10

CREATE TABLE `t_follow_timeline_099` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT ,
  `uid` bigint(20) NOT NULL DEFAULT '0' ,
  `timeline_id` varchar(32) NOT NULL ,
  `timeline_owner` bigint(20) NOT NULL DEFAULT '0' ,
  `status` tinyint(4) NOT NULL DEFAULT '1' ,
  `timeline_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ,
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ,
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ,
  PRIMARY KEY (`id`),
  KEY `idx_uid` (`uid`),
  KEY `idx_create_time` (`create_time`),
  KEY `idx_uid_timeline_owner` (`uid`,`timeline_owner`),
  KEY `idx_uid_timeline_id` (`uid`,`timeline_id`),
  KEY `idx_uid_create_time` (`uid`,`create_time`),
  KEY `idx_uid_status` (`uid`,`status`)
) ENGINE=InnoDB AUTO_INCREMENT=1091861159388237825 DEFAULT CHARSET=utf8 

第一页优化

## 第一页查询
mysql> explain SELECT *
    -> FROM t_follow_timeline_099
    -> force index (idx_uid_status)
    -> WHERE UID = 1833901412800099
    -> AND status = 1
    -> ORDER BY create_time DESC
    -> LIMIT 10;
+----+-------------+-----------------------+------------+------+----------------+----------------+---------+-------------+------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------------------+------------+------+----------------+----------------+---------+-------------+------+----------+---------------------------------------+
| 1 | SIMPLE | t_follow_timeline_099 | NULL | ref | idx_uid_status | idx_uid_status | 9 | const,const | 2875 | 100.00 | Using index condition; Using filesort |
+----+-------------+-----------------------+------------+------+----------------+----------------+---------+-------------+------+----------+---------------------------------------+
1 row in set, 1 warning (0.00 sec)

# 执行时间
10 rows in set (0.02 sec)

修改排序为order by id、自然なプライマリキーとセカンダリインデックスは、直接IDに基づいてソート返すので

#修改成 order by id 
SELECT *
FROM t_follow_timeline_099
force index (idx_uid_status)
WHERE UID = 1833901412800099
  AND status = 1
ORDER BY id DESC
LIMIT 10
#查询耗时: 0.001135 秒

力指数を削除、主キーと合併するように見えます

调整索引, 二级索引带上主键

mysql> alter table t_follow_timeline_099 add index idx_uid_status_id(`uid`,`status`,`id`) , drop index idx_uid_status;
Query OK, 0 rows affected (1 min 7.67 sec)
Records: 0 Duplicates: 0 Warnings: 0

翻页查询 通过id实现

mysql> explain SELECT * FROM t_follow_timeline_099 WHERE UID = 1833901412800099 AND status = 1 and id < 1090943061166186580 ORDER BY id DESC LIMIT 10;
+----+-------------+-----------------------+------------+-------+--------------------------------------------------------------------------------------------------+-------------------+---------+------+------+----------+-----------------------+
----+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-----------------------+------------+-------+--------------------------------------------------------------------------------------------------+-------------------+---------+--

| 1 | SIMPLE | t_follow_timeline_099 | NULL | range | PRIMARY,idx_uid,idx_uid_timeline_owner,idx_uid_timeline_id,idx_uid_create_time,idx_uid_status_id | idx_uid_status_id | 17 | NULL | 2774 | 100.00 | Using index condition |
+----+-------------+-----------------------+------------+-------+--------------------------------------------------------------------------------------------------+-------------------+---------+------+------+----------+-----------------------+


查询耗时: 0.00155 秒

最適化の概要

ステートメントオプティマイザによってオーダー上のMySQL

  1. 後者の条件は、それは好ましい順序がidであるインデックスフィールド
  2. 主キーのインデックスが来ることはありませんidで順番を確保するためには、複合インデックス、およびid続く必要があります
  3. 最後に、インデックスプラスIDの組み合わせが、サーバレイヤが識別可能にすることで、ストレージエンジンのレベルで、実施計画の主キーに到達回避は全く同じです
  4. + 0かなり良くIDによるオーダーよりもこれを達成するための最もエレガントな方法これは間違いなくインデックスに主キーを取得し、上記の方法でも可能であるではありませんので、
  5. ID制限10によって順序は、現在の行は、計画の実施に反映されません。例えば:IDリミット10によってidx_uid_status_id、条件はuid = 123、ステータス= 1順序は、key_lenにUID_STATUS長はまだですが、クイックリターンを並べ替えられません

おすすめ

転載: www.cnblogs.com/jesper/p/2c1ee93e1f9947d0b2e41cf9f9009665.html