Это не «наихудший» случай.
- Сделайте ключ
UNIQUE
случайным, вместо того, чтобы находиться в шаге блокировки с PK.Примером этого является UUID()
. - Генерирование достаточного количества строк, чтобы таблица и индекс (ы) не могли поместиться в buffer_pool.
Если вы оба из них, в конечном итоге вы будетеНаблюдайте, как значительно замедляется производительность.
UNIQUE
ключи оказывают следующее влияние на INSERTs
: ограничение уникальности проверяется перед возвратом клиенту.Для неуникального индекса работа по вставке в BTree индекса может (и является) отложена.(см. «Изменить буфер»). Без индекса во втором столбце работы еще меньше.
WHERE number=2002
-
- С
UNIQUE(number)
- Детализациявниз по BTree. Очень быстрый, очень эффективный. - с
INDEX(number)
- развернуть BTree. Очень быстрый, очень эффективный. Однако он немного медленнее, поскольку не может предположить, что существует только один такой рядТо есть после нахождения правильного места в BTree он будет сканировать вперед (очень эффективно), пока не найдет значение, отличное от 2002. - Без индекса
number
- Сканирование всей таблицы.Таким образом, стоимость зависит от размера таблицы, а не от значения number
. Она не имеет ни малейшего понятия, существует ли где-нибудь в таблице 2002 год или сколько раз. Если вы построите график времени, которое вы получили, вы увидите, что он довольно линейный.
Я предлагаю вам использовать log-log 'paper' для вашего графика. В любом случае, обратите внимание, насколько линейным является неиндексированный регистр. И индексированный регистр по существу постоянен. Нахождение числа = 200002 так же, какдешево как найти число = 2002. Это относится к UNIQUE
и INDEX
.(На самом деле в линии наблюдается очень небольшое увеличение, потому что BTree - это действительно O (log n), а не O (1). Для строк 2K в BTree, вероятно, есть 2 уровня; для 200K - 3 уровня.)
Кеш запросов может сбить вас с толку в моменты времени (если он включен).При выборе времени сделайте SELECT SQL_NO_CACHE ...
, чтобы избежать контроля качества.Если контроль качества включен и применяется, то выполнение второго и последующих запросов идентичных займет очень близко к 0,000 секунд.
Те временные интервалы, которые варьировались между 0,5мс и 1,2 мс - мела до фазы луны.Серьезно, нельзя доверять любому времени менее 10 мс.Это из-за всех других вещей, которые могут происходить на компьютере одновременно.Вы можете несколько умерить его, усреднив несколько запусков - обязательно избегая (1) кеша запросов и (2) ввода / вывода.
Что касается ввода / вывода ... Это возвращается к моему ранеепрокомментируйте, что может произойти, если таблица (и / или индекс) больше, чем может быть кэширована в ОЗУ.
- Если размер меньше ОЗУ, то при первом запуске может быть получено содержимое с диска.Второй и последующие запуски, вероятно, будут более быстрыми и последовательными.
- Поскольку объем больше, чем ОЗУ, все запуски могут потребоваться для попадания на диск.Следовательно, all может быть медленным и, возможно, более ненадежным, чем найденные вами варианты.
Ваши теги технически неверны.Большинство индексов MySQL - это BTrees (фактически B + Trees), а не Binary Trees.(Конечно, есть много общего, и многие принципы разделены.)
Возвращаясь к цели вашего исследования.
- Предположим, что есть "фоновый шум", который мешаетс вашими цифрами.
- Сделайте ваши тесты нетривиальными (например, неиндексированный регистр), чтобы он подавлял шум, или
- Повторите время, чтобы скрыть проблему.И обязательно не обращайте внимания на первый запуск.
Стоимость main при выполнении любого SELECT
равна количеству строк, к которым он прикасается.
- Сваш
UNIQUE
индекс, он касается 1 строки.Так что ожидайте быстро и O (1) (плюс шум). - Без индекса это касается N строк для таблицы N-строк.Так что ожидайте O (N).