次の表とデータがあるとします。
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はデフォルトでレコードをどのようにソートしますか?
SQL Serverに関する同様の質問への再投稿 私の答え :
SQLの世界では、順序はデータセットの固有のプロパティではありません。したがって、ORDER BY句を使用してデータをクエリしない限り、データが特定の順序で(または一貫した順序で)返されるというRDBMSからの保証はありません。
だから、あなたの質問に答えるには:
ORDER BY
を使用して目的の順序を指定する必要があります。他に何かをすることは、歓迎されない驚きに備えて自分を設定することです。これは、MySQLだけでなく、すべてのSQLのプロパティです。 SQL-92仕様 の関連テキストは次のとおりです。
<order by句>が指定されていない場合、Qの行の順序は実装に依存します。
カーソルの仕様にも同様のテキストが含まれています。
ORDER BY
句がない場合の行の順序は次のとおりです。
挿入は到着時に無秩序で無秩序です。作成されたインデックスには、インデックスであるリンクリストの適切な場所に要素が挿入される順序があります。あるインデックス要素から次のインデックス要素への順方向リンク、トラバースと整合性のための逆方向リンク、そしてテーブル内の実際のレコードへの一連のポインタがある、インデックスの3つのリンクリストを考えてください。問題のインデックス付き要素と一致します。
実際のデータ、無秩序なストレージ。データに関連付けられたインデックス。ストレージと構築で順序付けられます。データの実際のプルは、順序付けされているかどうかに関係なく、関連するクエリによって異なります。
MEMORYストレージエンジン になると、デフォルトのインデックスなので、挿入順であることが期待されます。レイアウトはHASH
ではなくBTREE
であり、インデックスレイアウトのどちらの側面も使用されていません。 kにインデックスを付け、kは同じ値であるため、すべてのキーはsameハッシュバケットに入ります。ハッシュバケットへの入力に複雑性が加わると想定する理由はないため、挿入の順序が最も理にかなっています。
同じサンプルテーブルとデータを取得して30 INSERT
s実行したところ、次のようになりました。
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また、バージョン固有の質問への回答を推奨しないよう丁寧に指摘してくれたことにも感謝します。彼らは両方とも今日私の賛成票を獲得します。