No InnoDB , as linhas são armazenadas em ordem de chave primária. Se você usar
LIMIT
sem ORDER BY
, você sempre obterá as linhas com os valores de chave primária mais baixos, mesmo que as tenha inserido em ordem aleatória. 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 |
+----+------+------+
No MyISAM , as linhas são armazenadas onde quer que caibam. Inicialmente, isso significa que as linhas são anexadas ao arquivo de dados, mas à medida que você exclui linhas e insere novas, as lacunas deixadas pelas linhas excluídas serão reutilizadas por novas linhas.
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
+----+------+------+
Outro caso de exceção se você usar o InnoDB é se estiver recuperando linhas de um índice secundário em vez do índice primário. Isso acontece quando você vê a nota "Usando índice" na saída EXPLAIN.
alter table foo add index (x);
select id, x from foo;
+----+------+
| id | x |
+----+------+
| 5 | A |
| 9 | B |
| 2 | C |
| 4 | D |
| 1 | E |
+----+------+
Se você tiver consultas mais complexas com junções, fica ainda mais complicado, pois você obterá as linhas retornadas pela ordem padrão da primeira tabela acessada (onde "primeiro" depende do otimizador escolher a ordem das tabelas), então as linhas da tabela unida serão dependentes da ordem das linhas da tabela anterior.
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 |
+----+------+------+----+------+------+
A conclusão é que é melhor ser explícito:quando você usa
LIMIT
, especifique um ORDER BY
.