Вопрос по database-design, postgresql, database, sql – PostgreSQL: определение первичного ключа в большой базе данных

9

Я планирую базу данных для хранения большого количества текста. (сообщения в блогах, новостные статьи и т. д.) В базе данных должны быть поля заголовка, содержимого (не более 50 000 символов), даты, ссылки и языка. Один и тот же контент не может встречаться по одной ссылке. Старый контент (например, старше 30 дней) будет удален.

Теперь проблема является первичным ключом. Я мог бы просто установить автоматически увеличивающееся поле (тип SERIAL) и использовать его в качестве первичного ключа. Но это кажется глупым и пустой тратой дискового пространства, потому что поле не будет служить какой-либо цели, кроме как быть первичным ключом. (и поле может в конечном итоге закончиться, или нет?) И всегда есть другая проблема с производительностью: содержимое каждой новой вставленной строки необходимо проверять на наличие дубликатов. Таким образом, другое решение для первичного ключа, который я придумал, состоит в том, чтобы вычислить хэш sha256 для содержимого + значение ссылки, а затем поместить его в новый хэш. столбец и использовать его в качестве первичного ключа. Две птицы с одним камнем. Конечно, проблема в том, что это хеш-коллизии. Это большая угроза?

У меня нет никакого опыта работы с PostgreSQL и очень мало опыта работы с СУБД в целом, поэтому я был бы признателен за второе мнение перед созданием базы данных с характеристиками производительности улитки на шоссе (ужасное сравнение).

Пожалуйста, помогите мне, если у вас есть опыт работы с большими базами данных. Является ли установка 64-символьной строки в качестве поля первичного ключа хорошей идеей в моей ситуации? (потому что у меня сложилось впечатление, что обычно этого избегают)

Ваш Ответ

6   ответов
1

люча. Я не думаю, что вы очень скоро превысите это число :-) Вся Википедия насчитывает около 3,5 миллионов статей ... Если бы вы писали 1000 статей в день, для достижения максимума целочисленного типа потребовалось бы почти 6000 лет.

9

зы данных (200 ГБ +), выиграл большой сериал с большим отрывом Это было быстрее генерировать, быстрее объединять, меньше кода, меньше занимаемая площадь. Из-за того, как postgres хранит его, bigint незначителен по сравнению с обычным int. Вам не хватит места для хранения вашего контента задолго до того, как вам придется беспокоиться о переполнении bigint. Сделав вычисленный хэш против bigint - полностью замените bigint.

Были ли в ваших тестах «другая проблема с производительностью: необходимо ли проверять содержимое каждой новой вставленной строки на наличие дубликатов»?
1

что вставки оказываются в случайном порядке в таблице, и это становится очень дорогостоящим, поскольку вещи должны быть перераспределены (хотя Postgres на самом деле не применяется так, как это делают другие). Я предлагаю последовательный первичный ключ, который может быть мелкозернистой временной меткой / временной меткой с последующим порядковым номером, позволяющим убить двух зайцев, и второй уникальный индекс, содержащий ваши хэш-коды. Имейте в виду, что вы хотите сохранить свой первичный ключ в виде меньшего (64-битного или менее) столбца.

Смотрите таблицу наhttp://en.wikipedia.org/wiki/Birthday_attack#The_mathematics так что вы можете быть уверены, что не столкнетесь.

Не забудьте пылесосить.

3

прежде чем закончится целое число первичного ключа.

Целое число будет быстрее для соединений, чем первичный ключ строки из 64 символов. Кроме того, людям, пишущим запросы, гораздо проще иметь дело с ними.

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

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

But, it seems stupid and a waste of disc space, because the field wouldn't serve any purpose but to be a primary key.

Поскольку суррогатный первичный ключ всегда должен быть бессмысленным, кроме как первичным ключом, я не уверен, каким будет ваше возражение.

Я планирую иметь много строк в таблице. Старые строки будут удалены, но поле будет продолжать автоматически увеличивать количество строк, поэтому, когда последовательное поле достигает 2147483647, я не могу получить больше строк в таблице, даже если таблица может быть наполовину пустой. KRTac
Мои 2 цента: сделать первичный ключ 64-битным int и добавить еще один столбец для вашего хэша.
Почти наверняка. Хеш в четыре раза больше размера (256 бит).
Вы ссылаетесь на 32-разрядное целое число со знаком. Для 64-разрядного целого числа со знаком максимальное значение составляет 9 223 372 036 854 775 807. Я сомневаюсь, что вы когда-нибудь исчерпаете это.
Будет ли он быстрее, чем хеш, даже если это 64-битный int? KRTac
2

The disk storage of a 64 bit primary-key integer is negligible no matter how much content you have. You'll never collide SHA256, and using it as a unique id isn't a bad idea.

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

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

Нет, я собирался сказать, что хэш будет изменен, но это было до чтения Lars & apos; ответ. KRTac
Ларс делает хорошую мысль. Хотя я все еще думаю, что алгоритмически сгенерированный ключ лучше, чем последовательность, необходимость менять первичный ключ - это плохо.
Харви, хорошая мысль, но если бы изменить значение содержимого строки, то я бы проверил, существует ли хэш нового содержимого + ссылка уже существует. Если это так, никаких изменений не произойдет. KRTac
Если вы используете SHA256 в качестве первичного ключа, разве он не должен быть неизменным? Что произойдет, если значение контент + ссылка изменится?
Так что, если содержание меняется, вы создаете новую запись?
3

т.е. ключ, который не является частью бизнес-данных вашего приложения. Требования к дополнительному пространству для дополнительного 64-разрядного целого числа, когда вы имеете дело с до 50 килобайт текста на запись, незначительны. Вы на самом деле будете использоватьless пробел, как только вы начнете использовать этот ключ в качестве внешнего ключа в других таблицах.

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

PS. Подобный вопрос был задан и дан ответ здесьдо.

Вот еще одна хорошая статья о теме: http://www.agiledata.org/essays/keys.html

Отличный совет, и я согласен с большинством из них. Но, как я упоминал ранее, что, когда ключ суррогата достигает 2147483647? Я мог бы использовать bigserial, но что скажется на производительности? KRTac
В этом контексте (хранение сообщений в блогах и новостных статей) я сомневаюсь, что достижение 2 ^ 31 пунктов было бы очень вероятно. Несмотря на это, если вы хотите планировать заранее, не рисковать и использовать bigserial, я бы сказал, что результативность будет минимальной, особенно по сравнению с использованием CHAR (32) в качестве PK.

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