Каков порядок записей по умолчанию для оператора SELECT в MySQL?

Предположим, что у вас есть следующая таблица и данные:

  создать таблицу t (
    k int,
    v int,
    индекс k (k)
    ) engine = память;

вставить в t (k, v)
значения (10, 1),
       (10, 2),
       (10, 3);
 

При выпуске select * from t where k = 10 без предложения by , как MySQL сортирует записи по умолчанию?

48 голосов | спросил daisy 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 22 Sep 2011 08:22:59 +0400 2011, 08:22:59

4 ответа


54

Перераспределение мой ответ на аналогичный вопрос о SQL Server:

  

В мире SQL порядок не является неотъемлемым свойством набора данных.   Таким образом, вы не получаете никаких гарантий от вашей РСУБД, что ваши данные придут   обратно в определенном порядке - или даже в последовательном порядке - если только вы   запросите свои данные с предложением ORDER BY.

Итак, чтобы ответить на ваш вопрос:

  • MySQL сортирует записи, но не хочет гарантировать согласованность.
  • Если вы намерены полагаться на этот заказ на что угодно, , вы должны указать желаемый заказ, используя ORDER BY . Сделать что-нибудь еще - это настроить себя на неприятные сюрпризы.

Это свойство всего SQL, а не только MySQL. Соответствующий текст в спецификации SQL-92 :

  

Если предложение <order by> не указывается, тогда упорядочение строк Q зависит от реализации.

В курсорах есть похожие биты текста.

ответил Nick Chammas 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 22 Sep 2011 09:40:53 +0400 2011, 09:40:53
18

Порядок строк в отсутствии предложения ORDER BY может быть:

  • разные между любыми двумя системами хранения;
  • Если вы используете один и тот же механизм хранения, он может отличаться между любыми двумя версиями одного и того же механизма хранения; Пример здесь , прокрутите вниз до "Порядок строк".
  • , если версия движка хранилища одинаков, но версия MySQL отличается, она может отличаться из-за изменений оптимизатора запросов между этими версиями;
  • Если все одно и то же, оно может быть другим из-за фазы луны, и это нормально.
ответил Laurynas Biveinis 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 22 Sep 2011 16:36:42 +0400 2011, 16:36:42
9

Внесение неуместно, хаотично, по прибытии. Созданный индекс имеет порядок, в котором элементы вставлены в соответствующее место в связанном списке, который является индексом. Подумайте о тройном связанном списке для индекса, где у вас есть прямая движущаяся ссылка от одного элемента индекса к следующему, обратная ссылка для целей обхода и целостности, а затем набор указателей на фактические записи в таблице, которые соответствуют указанному индексированному элементу.

Фактические данные, хаотичные по хранению. Индекс, связанный с данными, заказанный в хранилище и строительстве. Фактический выбор данных, упорядоченный или неупорядоченный, зависит от запроса.

ответил James Pulley 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 22 Sep 2011 17:44:43 +0400 2011, 17:44:43
2

Когда дело доходит до ПАМЯТЬ , я бы ожидал, что порядок будет иметь порядок вставки, потому что макет индекса по умолчанию HASH вместо BTREE и ни один аспект макета индекса. Поскольку вы проиндексировали k, а k - одно и то же значение, все клавиши входят в хэш-таблицу одинаковый . Поскольку нет причин предполагать добавленную сложность для заполнения хэш-ведра, порядок вставки имеет наибольший смысл.

Я взял ту же таблицу и данные примера и выполнил 30 INSERT s, и я получил это:

  MySQL & GT; использовать тест
Изменена база данных
MySQL & GT; drop table if существует t;
Запрос ОК, 0 строк, затронутых (0.00 сек)

MySQL & GT; create table t (k int, v int, index k (k)) engine = память;
Запрос ОК, 0 строк, затронутых (0.00 сек)

MySQL & GT; вставлять в значения t
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Запрос ОК, 30 строк (0.00 сек)
Записи: 30 Дубликаты: 0 Предупреждения: 0

MySQL & GT; выберите * из 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 строк в наборе (0,00 сек)

MySQL & GT;
 

Я решил проверить добавление двух разных значений для k: 10 и 11, я получил это:

  MySQL & GT; использовать тест
Изменена база данных
MySQL & GT; drop table if существует t;
Запрос ОК, 0 строк затронуты (0,02 сек)

MySQL & GT; create table t (k int, v int, index k (k)) engine = память;
Запрос ОК, 0 строк затронуты (0,01 сек)

MySQL & GT; вставлять в значения t
    - & GT; (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Запрос ОК, 30 строк (0.00 сек)
Записи: 30 Дубликаты: 0 Предупреждения: 0

MySQL & GT; выберите * из 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 строк в наборе (0,00 сек)

MySQL & GT;
 

Похож на порядок вставки. k = 11 был первым ключом хэшированного тогда 10. Как насчет вставки 10 сначала вместо 11? Это то, что я получил:

  MySQL & GT; использовать тест
Изменена база данных
MySQL & GT; drop table if существует t;
Запрос ОК, 0 строк затронуты (0,02 сек)

MySQL & GT; create table t (k int, v int, index k (k)) engine = память;
Запрос ОК, 0 строк, затронутых (0.00 сек)

MySQL & GT; вставлять в значения t
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    - & GT; (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Запрос ОК, 30 строк (0.00 сек)
Записи: 30 Дубликаты: 0 Предупреждения: 0

MySQL & GT; выберите * из 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 строк в наборе (0,00 сек)

MySQL & GT;
 

Это единодушное !!! ПОРЯДОК ВСТАВКИ - это ответ.

Сидениты при использовании индексов для механизма хранения 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   может привести к неожиданным результатам. Конкретный заказ без ORDER BY - это   побочный эффект механизма хранения и реализация оптимизатора запросов   который может и будет изменяться между младшими версиями MySQL.

Это была хорошая ссылка для меня сегодня. Ответ, который я дал, показал, что загруженная таблица была восстановлена, чтобы я ожидал СЕГОДНЯ в MySQL 5.5.12. Как только что указал Percona и @Laurynas Biveinis , в другом незначительном выпуске нет гарантии.

Итак, вместо того, чтобы пытаться защитить мой ответ, я бы предпочел ответить на ответ от @Laurynas Biveinis , потому что это самая последняя информация. Кудо и шляпы для @Laurynas Biveinis . Я также хотел бы поблагодарить @eevar за вежливое указание не продвигать ответы на вопросы, связанные с версией. Они оба получают мой верхний план сегодня.

ответил RolandoMySQLDBA 22 ndEurope/Moscowp30Europe/Moscow09bEurope/MoscowThu, 22 Sep 2011 15:40:32 +0400 2011, 15:40:32

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132