MySQLデータベースに数千の行がある場合、クエリを使用するTOP
かLIMIT
、クエリを高速化することは知っていますが、データの順序はデフォルトでデータベースですか?
そして、order by time
またはusername
をデフォルトで使用してTOP
、またはLIMIT
を簡単かつ高速に使用するにはどうすればよいですか?
MySQLデータベースに数千の行がある場合、クエリを使用するTOP
かLIMIT
、クエリを高速化することは知っていますが、データの順序はデフォルトでデータベースですか?
そして、order by time
またはusername
をデフォルトで使用してTOP
、またはLIMIT
を簡単かつ高速に使用するにはどうすればよいですか?
InnoDBでは、行は主キーの順序で格納されます。LIMIT
なしで使用するとORDER BY
、ランダムな順序で挿入した場合でも、主キー値が最も低い行が常に取得されます。
create table foo (id int primary key, x char(1), y int) engine=InnoDB;
insert into foo values (5, 'A', 123);
insert into foo values (9, 'B', 234);
insert into foo values (2, 'C', 345);
insert into foo values (4, 'D', 456);
insert into foo values (1, 'E', 567);
select * from foo;
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | E | 567 |
| 2 | C | 345 |
| 4 | D | 456 |
| 5 | A | 123 |
| 9 | B | 234 |
+----+------+------+
MyISAMでは、行は適切な場所に格納されます。最初は、これは行がデータファイルに追加されることを意味しますが、行を削除して新しい行を挿入すると、削除された行によって残されたギャップが新しい行によって再利用されます。
create table bar (id int primary key, x char(1), y int) engine=MyISAM;
insert into bar values (1, 'A', 123);
insert into bar values (2, 'B', 234);
insert into bar values (3, 'C', 345);
insert into bar values (4, 'D', 456);
insert into bar values (5, 'E', 567);
select * from bar;
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | A | 123 |
| 2 | B | 234 |
| 3 | C | 345 |
| 4 | D | 456 |
| 5 | E | 567 |
+----+------+------+
delete from bar where id between 3 and 4;
insert into bar values (6, 'F', 678);
insert into bar values (7, 'G', 789);
insert into bar values (8, 'H', 890);
select * from bar;
+----+------+------+
| id | x | y |
+----+------+------+
| 1 | A | 123 |
| 2 | B | 234 |
| 7 | G | 789 | <-- new row fills gap
| 6 | F | 678 | <-- new row fills gap
| 5 | E | 567 |
| 8 | H | 890 | <-- new row appends at end
+----+------+------+
InnoDBを使用する場合の別の例外ケースは、プライマリインデックスからではなくセカンダリインデックスから行を取得する場合です。これは、EXPLAIN出力に「インデックスの使用」という注記が表示されている場合に発生します。
alter table foo add index (x);
select id, x from foo;
+----+------+
| id | x |
+----+------+
| 5 | A |
| 9 | B |
| 2 | C |
| 4 | D |
| 1 | E |
+----+------+
結合を使用したより複雑なクエリがある場合は、アクセスされた最初のテーブルのデフォルトの順序(「first」はテーブルの順序を選択するオプティマイザーに依存します)によって返される行を取得するため、さらに複雑になります。結合されたテーブルの行は、前のテーブルの行の順序に依存します。
select straight_join foo.*, bar.* from bar join foo on bar.x=foo.x;
+----+------+------+----+------+------+
| id | x | y | id | x | y |
+----+------+------+----+------+------+
| 1 | E | 567 | 5 | E | 567 |
| 5 | A | 123 | 1 | A | 123 |
| 9 | B | 234 | 2 | B | 234 |
+----+------+------+----+------+------+
select straight_join foo.*, bar.* from foo join bar on bar.x=foo.x;
+----+------+------+----+------+------+
| id | x | y | id | x | y |
+----+------+------+----+------+------+
| 5 | A | 123 | 1 | A | 123 |
| 9 | B | 234 | 2 | B | 234 |
| 1 | E | 567 | 5 | E | 567 |
+----+------+------+----+------+------+
肝心なのは、明示するのが最善だということです。を使用するときはLIMIT
、を指定しますORDER BY
。
TOPまたはLIMITの使用が簡単かつ迅速になるように、デフォルトで時間またはユーザー名で注文するにはどうすればよいですか?
InnoDBをエンジンとして使用する場合、1つのインデックス(その列またはコレクション)を主キーとして設定できます。これらの値が一意である場合、保存時にそのように順序付けられます。
通常のインデックスを使用して、クエリ条件の一部として使用されている場合、またはクエリがすべての行からデータを取得する場合は、並べ替えを高速化できます。条件がソートしているフィールドのインデックス以外の他のインデックスを使用している場合、それらは役に立ちません。
次の表があるとします。
| username (Primary) | time (Index) | country |
これらのクエリには、インデックスを使用する並べ替えがあります。
select * from users order by time #Will use the index
select * from users where time between X and Y order by time #Will also use the index
Thiseは(ほとんどの場合...)ソートにインデックスを使用しません:
select * from users where country = China order by time
通常は挿入順に出てきますが、頼りにできません。特定の順序が必要な場合は、常に指定してください。
「time」と「username」にインデックスを追加して高速化し、必要なデータのみを選択します。
「デフォルト」の順序は指定されていません(つまり、信頼できません)
確実にするために、selectにORDERBY句を追加してください。