49904


インデックスが  
COL_A  
COL_B  
COL_C  
の列で作成されている時、

[code]

    ORDER BY
      COL_A
    , COL_B
    , COL_C
    
[/code]

はインデックスが作成されていない時と比較して高速に動作すると考えてよいでしょうか。

また

[code]

    WHERE
      COL_A = 'HOGE'
    ORDER BY
      COL_B
    , COL_C
    
[/code]

のような場合でも、並び替えに関してインデックスは有効利用されるでしょうか？  
効果があるかどうかはRDBによって異なるでしょうか。


CC BY-SA 4.0
2018-11-01T12:31:11.147
49862
2018-11-02T14:02:52.063
3925
question
mysql sql database sql-server oracle
インデックスと ORDER BY の関係について


実際に効果があるかどうかは、 RDB の実装次第であるとは思いますが、基本的に、今回のインデックスが COL_A, COL_B, COL_C
の３つの列に関する複合インデックスであり、かつ、例示されている select 文を実行するのであるならば、モダンな RDB
であるならば高速な動作は期待出来ると思います。

具体的には、 index は基本的に BTREE でその指定されたカラムを辞書順的に保持していると考えられますが、その BTREE
上で取得しやすいクエリであるならば、高速な検索が行われることが期待できます。

以下、普段自分が用いている MySQL について動作を検証しました。

[code]

    CREATE TABLE `test` (
      `COL_A` int,
      `COL_B` int,
      `COL_C` int,
      KEY `index_on_cols` (`COL_A`,`COL_B`,`COL_C`)
    ) ENGINE=InnoDB;
    
    insert into test(COL_A, COL_B, COL_C)
    with recursive one_to_hundred AS (
      select 1 as val
      UNION ALL
      select val + 1 as val from one_to_hundred where val < 100
    )
    select a.val, b.val, c.val
    from one_to_hundred as a cross join one_to_hundred as b cross join one_to_hundred as c;
    
[/code]

上記を実行すると、 1~100 の間から重複をゆるして３つ選んで、それぞれを COL_A, COL_B, COL_C としたようなデータを含む、レコード数
1,000,000 の `test` テーブルを作成できます。

mysql では、どのように select 文が実行されるかを explain で確認できるので、それぞれについてその結果を確認してみます。

### order by COL_A, COL_B, COL_C

sql 文:

[code]

    select * from test
    order by COL_A, COL_B, COL_C
    limit 100;
    
[/code]

実行計画:

[![order by COL_A, COL_B,
COL_C](https://i.stack.imgur.com/9zIX7.png)](https://i.stack.imgur.com/9zIX7.png)

実際に実行してみると: 0.00051 sec

### order by COL_C, COL_A, COL_B

sql 文:

[code]

    select * from test
    order by COL_C, COL_A, COL_B
    limit 100;
    
[/code]

実行計画:

[![order by COL_C, COL_A,
COL_B](https://i.stack.imgur.com/HxioS.png)](https://i.stack.imgur.com/HxioS.png)

実際に実行してみると: 0.449 sec

### where a = 30 order by COL_B, COL_C

sql 文:

[code]

    select * from test
    where COL_A = 30
    order by COL_B, COL_C
    limit 100;
    
[/code]

実行計画:

[![where a = 30 order by COL_B,
COL_C](https://i.stack.imgur.com/ib021.png)](https://i.stack.imgur.com/ib021.png)

実際に実行してみると: 0.00067 sec

### where COL_C = 30 order by COL_B, COL_A

sql 文:

[code]

    select * from test
    where COL_C = 30
    order by COL_B, COL_A
    limit 100;
    
[/code]

実行計画:

[![where COL_C=30 orderby COL_B,
COL_A](https://i.stack.imgur.com/T3xOU.png)](https://i.stack.imgur.com/T3xOU.png)

実際に実行してみると: 0.342 sec

# mysql について総括

index に沿ったクエリを発行する場合、たしかに効率的な動作をしている。


CC BY-SA 4.0
2018-11-02T13:57:23.350
49904
2018-11-02T14:02:52.063
2018-11-02T14:02:52.063
754
754
49862
answer