Відповіді:
Повторюючи свою відповідь на аналогічне запитання щодо SQL Server:
У світі SQL порядок не є притаманною властивістю набору даних. Таким чином, ви не отримуєте жодних гарантій від RDBMS, що ваші дані повернуться в певному порядку - або навіть у послідовному порядку - якщо ви не запитаєте свої дані за допомогою порядку ЗАМОВЛЕННЯ.
Отже, щоб відповісти на ваше запитання:
ORDER BY
. Робити що-небудь інше - це налаштувати себе на непрошені сюрпризи.Це властивість усіх SQL, а не тільки MySQL. Відповідний текст у специфікації SQL-92 :
Якщо <порядок за пунктом> не вказаний, то впорядкування рядків Q залежить від реалізації.
У специфікації для курсорів є аналогічні шматочки тексту.
Порядок рядків за відсутності ORDER BY
пункту може бути:
Вставлення не впорядковано, хаотично, після прибуття. Індекс, який створюється, має порядок, коли елементи вставляються у правильне розташування у пов'язаному списку, який є індексом. Придумайте потрійно зв'язаний список для індексу, де у вас є пряме рухоме посилання від одного елемента індексу до іншого, зворотнє посилання для цілей переходу та цілісності, а потім набір покажчиків на фактичні записи в таблиці, які збігаються з індексованим елементом.
Фактичні дані, хаотичні у зберіганні. Індекс, пов'язаний з даними, упорядкований для зберігання та побудови. Фактичний витяг даних, упорядкований чи не упорядкований, залежить від запиту.
Що стосується двигуна пам’яті MEMORY , я б очікував, що порядок буде в порядку вставки, оскільки HASH
замість цього макет індексу є замість, BTREE
і жоден аспект макета індексу не використовується. Оскільки ви індексували k, і k - це одне і те ж значення, всі ключі вводять одне і те ж хеш-відро. Оскільки немає причин вважати додаткові складності для заповнення хеш-відра, порядок вставки має найбільш сенс.
Я взяв ту саму вибіркову таблицю та дані і пробіг 30 INSERT
с, і я отримав це:
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>
Я вирішив перевірити, додавши два різних значення для k: 10 та 11.
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>
Схоже на порядок вставки. k = 11 було першим хешеваним ключем, то 10. Що робити вставлення 10 спочатку замість 11? Ось що я отримав:
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>
Це одностайно !!! ПОРЯДОК ВСТАВКИ - це відповідь.
Бачить використання індексів для двигуна пам'яті MEMORY
Пошук за діапазоном MEMORY мав би порівняно жахливі показники.
Створюючи індекс, ви можете вказати USING BTREE
пункт разом із визначенням індексу. Це покращило б питання для діапазону запитів.
Пошук конкретного рядка дасть однаковий результат у продуктивності з будь-яким HASH
або BTREE
.
ОНОВЛЕННЯ 2011-09-22 11:18 EDT
Я дізнався щось цікаве сьогодні. Я читаю посилання, яке надає @Laurynas Biveinis з Percona: Посилання Percona говорить щось про таблиці MEMORY для MySQL 5.5.15 :
Впорядкування рядків
У разі відсутності ORDER BY, записи можуть бути повернуті в іншому порядку, ніж попереднє виконання MEMORY. Це не помилка. Будь-яка програма, що покладається на певне замовлення без пункту ЗАМОВЛЕННЯ ПО БУДЬ, може дати неочікувані результати. Конкретне замовлення без ORDER BY - це побічний ефект реалізації механізму зберігання даних та оптимізатора запитів, який може і змінюватись між незначними випусками MySQL.
Це було гарним посиланням для мене сьогодні. Відповідь, яку я дав, продемонструвала, що завантажену я таблицю була отримана для того, щоб я очікував, що сьогодні в MySQL 5.5.12. Як тільки вказували Перкона та @Laurynas Biveinis , жодної гарантії в другому незначному звільненні немає.
Отже, замість того, щоб намагатися захистити свою відповідь, я б краще просувати відповідь від @Laurynas Biveinis, тому що це найновіша інформація. Кудо і шапки зняті для @Laurynas Biveinis . Я також хотів би подякувати @eevar за ввічливий вказівку на те, щоб не поширювати відповіді на запитання, що стосуються версії. Вони обидва сьогодні отримують мою підсумку.