Odpowiedzi:
Przesłanie mojej odpowiedzi na podobne pytanie dotyczące programu SQL Server:
W świecie SQL porządek nie jest nieodłączną właściwością zestawu danych. W ten sposób nie otrzymujesz żadnych gwarancji z RDBMS, że twoje dane wrócą w określonej kolejności - lub nawet w spójnej kolejności - chyba że zapytasz o swoje dane klauzulą ORDER BY.
Tak więc, aby odpowiedzieć na twoje pytanie:
ORDER BY
. Robienie czegokolwiek innego to przygotowywanie się na niepożądane niespodzianki.Jest to właściwość całego SQL, nie tylko MySQL. Odpowiedni tekst w specyfikacji SQL-92 to:
Jeśli nie podano <kolejność według klauzuli>, kolejność wierszy Q zależy od implementacji.
W specyfikacji kursorów znajdują się podobne fragmenty tekstu.
Kolejność wierszy bez ORDER BY
klauzuli może być następująca:
Wkładanie jest nieuporządkowane, chaotyczne, po przyjeździe. Utworzony indeks ma kolejność, w której elementy są wstawiane w odpowiedniej lokalizacji na połączonej liście, która jest indeksem. Pomyśl o potrójnie połączonej liście indeksu, w której masz ruchome łącze do przodu z jednego elementu indeksu do następnego, link do tyłu do celów przejścia i integralności, a następnie zestaw wskaźników do rzeczywistych rekordów w tabeli, które dopasuj indeksowany element, o którym mowa.
Rzeczywiste dane, chaotycznie w pamięci. Indeks związany z danymi, uporządkowany w pamięci i konstrukcji. Rzeczywiste pobieranie danych, uporządkowane lub nieuporządkowane, zależy od danego zapytania.
Jeśli chodzi o silnik pamięci MEMORY , oczekiwałbym, że kolejność będzie zgodna z kolejnością wstawiania, ponieważ HASH
zamiast tego domyślny układ indeksu BTREE
nie jest używany i żaden aspekt układu indeksu nie jest używany. Ponieważ zaindeksowałeś k, a k ma tę samą wartość, wszystkie klucze wchodzą do tego samego segmentu mieszania. Ponieważ nie ma powodu, aby zakładać dodatkową złożoność wypełniania segmentu mieszania, kolejność wstawiania jest najbardziej sensowna.
Wziąłem twoją próbną tabelę i dane i uruchomiłem 30 INSERT
s i otrzymałem to:
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>
Postanowiłem przetestować, dodając dwie różne wartości dla k: 10 i 11. Otrzymałem to:
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>
Wygląda na kolejność wstawiania. k = 11 to był pierwszy klucz zaszyfrowany, a następnie 10. Co powiesz na wstawienie 10 zamiast 11? Oto co mam:
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>
To jednogłośne !!! ZAMÓWIENIE WSTAWIENIA jest odpowiedzią.
Sidenotes na temat używania indeksów dla silnika pamięci MEMORY
Wyszukiwania MEMORY w zakresie zakresu miałyby porównywalnie przerażającą skuteczność.
Podczas tworzenia indeksu można określić USING BTREE
klauzulę wraz z definicją indeksu. Poprawiłoby to zakres zapytań o zakres.
Wyszukiwanie określonego wiersza da ten sam wynik w zakresie wydajności z jednym HASH
lub BTREE
.
AKTUALIZACJA 22.09.2011 11:18 EDT
Nauczyłem się dziś czegoś ciekawego. Przeczytałem link podany przez @Laurynas Biveinis z Percona: Link Percona mówi coś o tabelach MEMORY dla MySQL 5.5.15 :
Zamawianie rzędów
W przypadku braku ORDER BY rekordy mogą zostać zwrócone w innej kolejności niż poprzednia implementacja MEMORY. To nie jest błąd. Każda aplikacja oparta na konkretnym zamówieniu bez klauzuli ORDER BY może dawać nieoczekiwane wyniki. Określone zamówienie bez ORDER BY jest efektem ubocznym implementacji silnika pamięci i implementacji optymalizatora zapytań, który może i będzie się zmieniał między mniejszymi wersjami MySQL.
To był dla mnie dobry link do zobaczenia dzisiaj. Udzielona przeze mnie odpowiedź wykazała, że tabela, którą załadowałem, została pobrana w porządku, jakiego oczekiwałem DZIŚ w MySQL 5.5.12. Jak właśnie zauważyli Percona i @Laurynas Biveinis , nie ma gwarancji w innym mniejszym wydaniu.
Zamiast więc bronić mojej odpowiedzi, wolę promować odpowiedź od @Laurynas Biveinis, ponieważ jest to najbardziej aktualna informacja. Wyrazy uznania i czapki dla @Laurynas Biveinis . Chciałbym również podziękować @eevar za grzeczne zwrócenie uwagi na nie promowanie odpowiedzi na pytania dotyczące konkretnych wersji. Obaj otrzymali dziś moje poparcie.