Mysql
 sql >> Database >  >> RDS >> Mysql

Come vengono ordinati i dati in MySql per impostazione predefinita

In InnoDB , le righe vengono archiviate nell'ordine della chiave primaria. Se usi LIMIT senza ORDER BY , otterrai sempre le righe con i valori di chiave primaria più bassi, anche se le hai inserite in ordine casuale.

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 |
+----+------+------+

Nel mioISAM , le righe vengono archiviate dove si adattano. Inizialmente, ciò significa che le righe vengono aggiunte al file di dati, ma quando elimini le righe e ne inserisci di nuove, gli spazi lasciati dalle righe eliminate verranno riutilizzati dalle nuove righe.

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
+----+------+------+

Un altro caso di eccezione se si utilizza InnoDB è se si stanno recuperando righe da un indice secondario anziché dall'indice primario. Ciò accade quando vedi la nota "Uso dell'indice" nell'output 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 hai query più complesse con i join, diventa ancora più complicato, perché otterrai le righe restituite dall'ordine predefinito della prima tabella a cui si accede (dove "first" dipende dall'ottimizzatore che sceglie l'ordine delle tabelle), quindi le righe della tabella unita dipenderanno dall'ordine delle righe della tabella precedente.

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 |
+----+------+------+----+------+------+

La conclusione è che è meglio essere espliciti:quando usi LIMIT , specifica un ORDER BY .