W InnoDB , wiersze są przechowywane w kolejności klucza podstawowego. Jeśli używasz LIMIT
bez ORDER BY
, zawsze otrzymasz wiersze z najniższymi wartościami klucza podstawowego, nawet jeśli wstawisz je w kolejności losowej.
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 |
+----+------+------+
W MyISAM , wiersze są przechowywane w dowolnym miejscu. Początkowo oznacza to, że wiersze są dołączane do pliku danych, ale po usunięciu wierszy i wstawieniu nowych luki pozostawione przez usunięte wiersze zostaną ponownie wykorzystane przez nowe wiersze.
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
+----+------+------+
Innym wyjątkiem, jeśli używasz InnoDB, jest pobieranie wierszy z indeksu pomocniczego zamiast z indeksu podstawowego. Dzieje się tak, gdy zobaczysz uwagę „Korzystanie z indeksu” w danych wyjściowych EXPLAIN.
alter table foo add index (x);
select id, x from foo;
+----+------+
| id | x |
+----+------+
| 5 | A |
| 9 | B |
| 2 | C |
| 4 | D |
| 1 | E |
+----+------+
Jeśli masz bardziej złożone zapytania ze złączeniami, sprawa staje się jeszcze bardziej skomplikowana, ponieważ otrzymasz wiersze zwrócone według domyślnej kolejności pierwszej tabeli (gdzie „pierwszy” jest zależny od tego, czy optymalizator wybiera kolejność tabel), wtedy wiersze z połączonej tabeli będą zależne od kolejności wierszy z poprzedniej tabeli.
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 |
+----+------+------+----+------+------+
Najważniejsze jest to, że najlepiej jest być wyraźnym:kiedy używasz LIMIT
, określ ORDER BY
.