Последовательная генерация UID для MySQL Char () или другого поля - PullRequest
5 голосов
/ 16 ноября 2010

Пробовал Googling, но:

Вопрос : Лучший способ для внешней генерации последовательных значений UID для поля MySQL, которое должно быть представлено в виде строки.

Причина:
Общие последовательные значения UUID-ish для вставок на диске / добавление страниц для выполнения операций записи и префикса даты для скорости чтения при поиске индекса поля из char [0] вперед.Столбец будет проиндексирован, но в поиске лучших данных для повышения производительности чтения индекса и записи в таблицу, а не просто старый UUID.

Моя первоначальная мысль - это дата некоторой детализации (возможно, эпохи с добавлением), добавленной кили заменив некоторую часть сгенерированной UUIDv4 строки, например [Unix epoch][remaining UUID4], в поле char фиксированной ширины, но я не уверен, будет ли это иметь желаемый результат упорядочивания на странице / диске и результат поиска по индексу.Примером может быть:

12904645950049bceba1cc24e80806dd

Значения должны быть независимы от самого MySQL, следовательно, с использованием UUID и временных меток, а не какого-либо изменения автоинкремента.

Anyoneкто знает, что у внутренних индексов MySQL есть какие-либо предложения (для таблиц InnoDB)?

Aiden

Ответы [ 4 ]

5 голосов
/ 23 ноября 2010

Может быть немного оффтоп, но взгляните на снежинку Twitter . Они говорят, что это:

  • (Примерно) Заказанное время (очень помогает избежать дорогостоящих случайных обновлений BTREE первичного ключа)
  • Непосредственно Сортируемый
  • Компактный

Не говоря уже о других функциях (HA и т. Д.). Вы можете либо прозвать их алгоритм, либо просто использовать его как есть.

Весь UID использует только до 64 бит пространства, поэтому я думаю, это было бы весьма эффективно для индексации - см. http://www.mysqlperformanceblog.com/2006/10/03/long-primary-key-for-innodb-tables/ (пример счетчика).

3 голосов
/ 25 ноября 2010

Я думаю, что вам, возможно, нужно быть более конкретным с тем, что вы пытаетесь решить (в чем собственно проблема - почему не auto_increment ?, какова ваша предложенная схема? И т. Д.).Чтобы ответить на ваш внутренний вопрос:

  • InnoDB хранит данные в индексе (кластеризованном индексе) на 16 тыс. Страницах.

Риск не вставлять последовательно - как минимум двасвернуть:

  1. Если у вас недостаточно памяти, вам может потребоваться выполнить произвольный ввод-вывод, чтобы загрузить страницу с диска и вставить значение на эту страницу.

  2. Возможно, на странице не осталось свободного места (InnoDB заполняет 93% и оставляет небольшой пробел для обновлений), что может привести к необходимости разделения страницы.Больше разделенных страниц = фрагментация / менее оптимальное использование таких вещей, как память.

Итак, я думаю, что, по крайней мере, если вы приблизительно последовательны (1), это не касаетсяиндекс первичного ключа (все еще может быть истинным для любых уникальных индексов).Вам просто нужно беспокоиться о (2).


Почему я сказал, что понимание проблемы важно, потому что есть много способов сделать это, кроме длинных GUID.С одной стороны, BIGINT в MySQL меньше, чем любой тип данных, который вы, вероятно, будете использовать, но имеет диапазон 18 квинтиллионов.Вы можете выделить «порции» ключевого пространства N тысяч за один раз рабочим узлам и гарантировать отсутствие дубликатов.Если рабочий узел выходит из строя и не использует весь фрагмент, который был выделен, ну и что.Это не имеет значения.

2 голосов
/ 25 ноября 2010

Проверьте этот вопрос . Возможно, он не детализирует конкретное использование индексов MySQL, но дает некоторые данные о производительности и код для генерации Seq. UIDs.

Кажется, что индексирование MySQL значительно выигрывает от последовательных идентификаторов, и в соответствии с MySQL индексирование основывается на упорядочении дисков (см. Раздел: Характеристики индекса B-Tree ), чтобы найти соответствующий Результаты.

Из памяти индексация MySQL (по крайней мере для индексов String) основывается вначале на буквенно-цифровом порядке поля, т. Е. «О, это начинается с A? У меня есть данные, которые начинаются с A, я получу их для тебя ... и т. д. Вместо полнотекстового сканирования каждого поля.

И ввод UID последовательно означает, что индекс не переупорядочивает результаты «по алфавиту» в первую очередь или, по крайней мере, значительно сокращает это время, следовательно, вышеупомянутые преимущества в производительности, упомянутые выше.

(Не совсем решение, но ответ по крайней мере.)

1 голос
/ 26 ноября 2010

Что я делаю, так это использую символьное поле фиксированной ширины и добавляю случайную строку UUID к текущему времени (в миллисекундах). Это хорошо, потому что даже если к вашему серверу обращаются дважды за одну и ту же миллисекунду, он все равно (вероятно) будет уникальным. Я предполагаю, что если у вас массивная загрузка сервера, это может дать несколько идентификаторов, но если вас это беспокоит, вы можете проверить, не была ли уже создана строка с таким uuid.

PHP:

$date = new DateTime();
$UUID = uniqid( $date->format('Uu'), FALSE);  // For less length
$UUID = uniqid( $date->format('Uu'), TRUE);   // For more length

Это то, что я использую на своем (редко используемом) сервере. Но оно должно быть сильным для больших нагрузок. Как я уже сказал, чтобы преодолеть небольшую вероятность создания двух идентичных ключей, проверьте, не было ли оно уже использовано, и назначьте новый. (это не должно случаться слишком часто)

...