web-dev-qa-db-ja.com

MySQLのSELECTステートメントのレコードのデフォルトの順序は何ですか?

次の表とデータがあるとします。

create table t (
    k int,
    v int,
    index k(k)
    ) engine=memory;

insert into t (k, v)
values (10, 1),
       (10, 2),
       (10, 3);

select * from t where k = 10句なしでorder byを発行する場合、MySQLはデフォルトでレコードをどのようにソートしますか?

76
daisy

SQL Serverに関する同様の質問への再投稿 私の答え

SQLの世界では、順序はデータセットの固有のプロパティではありません。したがって、ORDER BY句を使用してデータをクエリしない限り、データが特定の順序で(または一貫した順序で)返されるというRDBMSからの保証はありません。

だから、あなたの質問に答えるには:

  • MySQLはレコードをソートしますが、一貫性は保証されません。
  • 何かをこの順序に依存する場合は、ORDER BYを使用して目的の順序を指定する必要があります。他に何かをすることは、歓迎されない驚きに備えて自分を設定することです。

これは、MySQLだけでなく、すべてのSQLのプロパティです。 SQL-92仕様 の関連テキストは次のとおりです。

<order by句>が指定されていない場合、Qの行の順序は実装に依存します。

カーソルの仕様にも同様のテキストが含まれています。

87
Nick Chammas

ORDER BY句がない場合の行の順序は次のとおりです。

  • 2つのストレージエンジン間で異なります。
  • 同じストレージエンジンを使用する場合、同じストレージエンジンの2つのバージョン間で異なる場合があります。 ここの例 、「行の順序」までスクロールします。
  • ストレージエンジンのバージョンは同じでもMySQLのバージョンが異なる場合、それらのバージョン間でクエリオプティマイザーが変更されているため、バージョンが異なる可能性があります。
  • すべてが同じである場合、月相のために異なる可能性があり、それは問題ありません。
29

挿入は到着時に無秩序で無秩序です。作成されたインデックスには、インデックスであるリンクリストの適切な場所に要素が挿入される順序があります。あるインデックス要素から次のインデックス要素への順方向リンク、トラバースと整合性のための逆方向リンク、そしてテーブル内の実際のレコードへの一連のポインタがある、インデックスの3つのリンクリストを考えてください。問題のインデックス付き要素と一致します。

実際のデータ、無秩序なストレージ。データに関連付けられたインデックス。ストレージと構築で順序付けられます。データの実際のプルは、順序付けされているかどうかに関係なく、関連するクエリによって異なります。

11
James Pulley

MEMORYストレージエンジン になると、デフォルトのインデックスなので、挿入順であることが期待されます。レイアウトはHASHではなくBTREEであり、インデックスレイアウトのどちらの側面も使用されていません。 kにインデックスを付け、kは同じ値であるため、すべてのキーはsameハッシュバケットに入ります。ハッシュバケットへの入力に複雑性が加わると想定する理由はないため、挿入の順序が最も理にかなっています。

同じサンプルテーブルとデータを取得して30 INSERTs実行したところ、次のようになりました。

mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.00 sec)

mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t values
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+
| k    | v    |
+------+------+
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
+------+------+
30 rows in set (0.00 sec)

mysql>

Kに2つの異なる値を追加してテストすることにしました。10と11です。

mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.02 sec)

mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t values
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+
| k    | v    |
+------+------+
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
+------+------+
30 rows in set (0.00 sec)

mysql>

挿入順のようです。 k = 11は最初のキーが10にハッシュされたものです。11ではなく10を最初に挿入するのはどうですか?これは私が得たものです:

mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.02 sec)

mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t values
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+
| k    | v    |
+------+------+
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
+------+------+
30 rows in set (0.00 sec)

mysql>

満場一致です!!!挿入の順序が答えです。

MEMORYストレージエンジンのインデックスの使用に関する注意事項

MEMORYの範囲検索は、かなり恐ろしいパフォーマンスになります。

インデックスを作成するときに、インデックスの定義とともにUSING BTREE句を指定できます。これにより、範囲クエリの処理が改善されます。

特定の行を検索すると、HASHまたはBTREEのどちらを使用しても同じ結果が得られます。

UPDATE 2011-09-22 11:18 EDT

今日は面白いことを学びました。 Perconaから@ Laurynas Biveinisによって提供されるリンクを読みます:Perconaリンクは、MySQL 5.5.15のMEMORYテーブルについて何かを述べています

行の順序

ORDER BYがない場合、レコードは以前のMEMORY実装とは異なる順序で返される可能性があります。これはバグではありません。 ORDER BY句のない特定の注文に依存するアプリケーションは、予期しない結果をもたらす可能性があります。 ORDER BYを使用しない特定の順序は、MySQLのマイナーリリース間で変更される可能性があり、また変更されるストレージエンジンとクエリオプティマイザーの実装の副作用です。

これは今日私が見る良いリンクでした。私が出した答えは、ロードしたテーブルが、MySQL 5.5.12でTODAYを期待したとおりに取得されたことを示していました。 Perconaと@ Laurynas Biveinisが指摘したように、別のマイナーリリースでは保証はありません。

ですから、私の答えを擁護しようとするのではなく、@ Laurynas Biveinisからの答えを宣伝したいと思います。これは最新の情報だからです。 @ Laurynas Biveinisに対する称賛と敬意を表します。 @ eevarまた、バージョン固有の質問への回答を推奨しないよう丁寧に指摘してくれたことにも感謝します。彼らは両方とも今日私の賛成票を獲得します。

5
RolandoMySQLDBA