Какой подход лучше использовать для первичного и внешнего ключа: автогенерируемый номер (autoincrement) или случайная строка?

Не совсем ясен следующий момент. У меня есть таблица с полями "text" и "hash", где "hash" является первичным ключом и содержит md5 хеш текста. Таблица часто используется в запросах с JOIN по полю hash. Будет ли более производительным добавить поле типа bigint с автоинкрементом в качестве первичного ключа и использовать его для JOIN? Я интересуюсь только скоростью чтения из базы данных, а не записи. База данных - MariaDB.
  • 30 сентября 2024 г. 12:33
Ответы на вопрос 2
При выборе между автогенерируемым номером (autoincrement) и случайной строкой, есть несколько важных факторов, которые стоит учитывать, особенно в контексте использования первичных ключей и производительности запросов в MariaDB.

### Плюсы и минусы использования автогенерируемого номера (autoincrement):

**Плюсы:**
1. **Скорость JOIN**: Автогенерируемый bigint является компактным типом данных (8 байт), что может быть более эффективно для хранения и индексации, особенно при больших объемах данных. Это также может ускорить операции JOIN.
2. **Упрощение индексации**: Поскольку значения всегда возрастают, индексы на таких полях будут "заполненными", что может повысить производительность.
3. **Легкость в использовании**: Простота в создании и использовании, особенно в больших таблицах.

**Минусы:**
1. **Не человеческое восприятие**: Цифровые идентификаторы могут быть менее удобными для интерпретаций и отладки, что может быть важно в некоторых случаях.

### Плюсы и минусы использования случайной строки / хеша (например, md5):

**Плюсы:**
1. **Уникальность на основе содержимого**: Хеширование позволяет легко проверять уникальность на основе содержимого, и если контент повторяется, вы будете иметь одинаковое значение hash.
2. **Сопоставимость**: У вас есть возможность идентифицировать строки не по номеру, а по их смыслу.

**Минусы:**
1. **Размер**: md5 занимает 16 байт (или 32 символа в строковом представлении), что может привести к большей нагрузке на память при больших объемах данных.
2. **Производительность JOIN**: JOIN по строковым полям обычно медленнее, чем по числовым, особенно при больших объёмах данных.

### Рекомендация

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

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

### Заключение

1. Используйте **bigint autoincrement** как первичный ключ.
2. Оставьте поле `hash` для уникальности и используйте его для целевых запросов.
3. Протестируйте оба подхода на ваших данных, поскольку результаты могут варьироваться в зависимости от структуры таблицы и типа запросов.
из той статьи появилось предположение

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

Таблица часто join-тся в запросах через hash.

Что, берутся все записи таблицы, и сортировка выходного набора тоже по этому полю? нет? тогда статья тут близко не лежала.

"hash" - это primary key и содержит md5 текста

Тип данных и размер мы должны сами придумать?
Похожие вопросы