Какой префикс использовать при индексировании строкового столбца SecureRandom

У меня есть столбец БД (тип varchar(255)), в котором хранится URL-безопасная строка base 64, созданная SecureRandom.urlsafe_base64. Вызов метода использует значения по умолчанию, поэтому результат должен быть 16 байт или 22 символа в длину.

Значение base64 используется для поиска записей, когда пользователь заходит на сайт, для маскировки идентификаторов БД. Мне нужен индекс для этого столбца из-за этого поиска, однако я не хочу индексировать весь столбец, потому что мог неэффективен для хранения.

Каков наилучший подход к определению оптимального префикса индекса для использования в этом случае? Я сейчас думаю примерно так:

  1. Создайте образцы данных, содержащие около 100 000 записей, для имитации производственных данных.
  2. Добавьте индекс для столбца base 64 с префиксом (скажем, 8 символов)
  3. Запустите EXPLAIN для поиска в столбце с основанием 64, чтобы увидеть, сколько записи должны быть проверены
  4. Отрегулируйте указатель вверх или вниз и повторите шаг 3.
  5. Выберите размер префикса, который уравновешивает (а) требования к хранилищу и (б) количество записей, возвращаемых с соответствующими обращениями.

Проблема здесь в том, что я знаю, что SecureRandom создает уникальные строки с основанием 64, но я не уверен, что это насколько уникален. Например, из 100 тыс. записей, если я использую префикс из 8 символов, будет ли этот префикс общим для 10 записей или 100?

Некоторые более конкретные вопросы о моем подходе:

  1. Достаточно ли 100 000 записей для выбора подходящего размера префикса?
  2. Если я применил индекс без с использованием префикса, правильно ли я подозреваю, что это плохо с точки зрения хранения?
  3. Какое разумное количество записей можно ожидать, чтобы запросить таблицу напрямую, и при этом извлечь выгоду из индекса?

Примечания:

  • Моя база данных MySQL (на самом деле Percona)
  • SecureRandom происходит от Руби
  • Я предполагаю, что функция URL-безопасности SecureRandom не меняет характеристики уникальности вывода base 64.

Зачем вам уникальность? Пока они равномерно распределены, индекс будет создавать сбалансированное количество сегментов и будет эффективным при извлечении данных. И я предполагаю, что SecureRandom производит довольно сбалансированные значения.

The Impaler 28.05.2019 02:50

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

The Impaler 28.05.2019 02:53

Почему бы не использовать SecureRandom.uuid тогда они будут уникальными.

Kris 28.05.2019 12:32
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
2
3
119
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это просто случайное число, верно? Не шифрование.

Использовать ли нет префикс; хотя это немного уменьшит размер индекса, во многих случаях это сделает использование индекса недействительным. Правда, 22 байта длиннее, чем 8-символьная строка или 4-байтовая INT. Но обратная сторона отказа от использования индекса еще хуже.

Значение по умолчанию 16 (22) достаточно, чтобы сделать случайную строку достаточно уникальной, чтобы избежать случайных столкновений.

Не говорите VARCHAR(255), если максимальное значение равно 22. Говорите CHAR(22), если длина фиксированная, или VARCHAR(22), если вы разрешаете пользователю выбирать длину до 16.

Скажите CHARACTER SET ascii COLLATE ascii_bin для столбца. Это позволит избежать (1) накладных расходов utf8 и (2) ошибки свертывания регистра.

Если вы собираетесь иметь индекс для миллиарда таких элементов, то возникнут серьезные проблемы с производительностью, как обсуждалось в здесь (хотя и в другом контексте). Миллион строк, вероятно, не проблема - это зависит от того, когда индекс станет больше, чем может быть кэшировано в ОЗУ в пуле буферов.

(Если я правильно помню формулу, для 8 символов, как вы описываете, будет один шанс на 300 КБ, что индекс с 300 000 записей будет включать дубликат. Но это не проблема.)

Ответ принят как подходящий

Результаты

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

В результате этого эксперимента произошли два изменения:

  1. Я уменьшил размер столбца с 255 до 22 (также предложено @Rick James). Подробнее см. в вопросе, почему данные никогда не превышают 22 символов.
  2. Я добавил индекс столбца с префиксом из 8 символов. Кодировка — utf8mb4, поэтому размер ключа не будет прямо пропорционален количеству символов в префиксе.

Сведения об эксперименте

Я протестировал префиксы длиной 1, 2, 4, 8 и 16 символов и использовал EXPLAIN, чтобы увидеть, что сделает поиск в столбце. Я также тестировал без индекса в качестве базовой линии. Мой эксперимент был основан на наборе из 100 тыс. записей. Я мог бы протестировать большее количество записей, но для моих целей не было необходимости в большей точности.

Вот некоторые моменты эксперимента:

  • Без индекса запрос в столбце SecureRandom выполняет сканирование таблицы.
  • С префиксом в 1 символ MySQL должен сканировать примерно 3200 записей по 100 тыс.
  • С двухсимвольным префиксом MySQL должен просмотреть 79 записей.
  • С префиксом из 4 символов MySQL сразу получает точную запись, не выполняя поиск в таблице.

Помимо 4-значного префикса, с набором данных 100 000 и исходя из характеристик SecureRandom.urlsafe_base64, я не могу быть более точным. Основываясь на текущем размере таблицы в производственной среде и приблизительном представлении о темпах ее роста, мы решили, что префикс из 8 символов сослужит нам хорошую службу в будущем, экономя при этом дисковое пространство и память.

Альтернативы

Благодаря этому исследованию я также узнал о функции избирательности индексов в MySQL. Это позволило бы, используя один и тот же выборочный набор из 100 000 записей, протестировать количество записей, извлеченных для каждой длины префикса, без необходимости выполнять миграции для добавления/удаления различных индексов перед каждым тестом. Например, чтобы проверить селективность 4-символьного префикса:

SELECT count(*) AS count, LEFT(uuid_column, 4) AS prefix
  FROM string_prefix_test GROUP BY count DESC LIMIT 10;

Более подробную информацию о селективности индекса можно найти в выпуске Высокая производительность MySQL 2012 года на стр. 160.

Будущая работа

Далее я собираюсь изучить префиксы для индексов столбцов varchar с данными, которые не обладают характеристиками уникальности SecureRandom.urlsafe_base64. Это будет сложнее только потому, что сложнее получить репрезентативный набор данных.

Другие вопросы по теме