Плюсы и минусы использования хэша MD5 в качестве первичного ключа и использования идентификатора int в качестве первичного ключа в SQL Server
у меня есть приложение для работы с файлом и его фрагментации на несколько сегментов, а затем сохраните результат в базе данных sql server. Существует много дублированных файлов (возможно, с другим путем к файлу), поэтому сначала я просматриваю все эти файлы и вычисляю хэш Md5 для каждого файла и отмечаю дублированный файл с помощью столбца [Duplicated].
затем каждый день я буду запускать это приложение и сохранять результаты в таблицу [Result]. Схемы БД в ниже:
CREATE TABLE [dbo].[FilePath]
(
[FilePath] NVARCHAR(256) NOT NULL PRIMARY KEY,
[FileMd5Hash] binay(16) NOT NULL,
[Duplicated] BIT NOT NULL DEFAULT 0,
[LastRunBuild] NVARCHAR(30) NOT NULL DEFAULT 0
)
CREATE TABLE [dbo].[Result]
(
[Build] NVARCHAR(30) NOT NULL,
[FileMd5Hash] binay(16) NOT NULL ,
[SegmentId] INT NOT NULL,
[SegmentContent] text NOT NULL
PRIMARY KEY ([FileMd5Hash], [Build], [SegmentId])
)
и у меня есть требование присоединиться к этим 2 таблицам на FileMd5Hash.
поскольку количество строк [Result] очень велико, я хотел бы добавить столбец идентификатора int, чтобы соединить их с таблицами, как показано ниже:
CREATE TABLE [dbo].[FilePath]
(
[FilePath] NVARCHAR(256) NOT NULL PRIMARY KEY,
[FileMd5Hash] binay(16) NOT NULL,
**[Id] INT NOT NULL IDENTITY,**
[Duplicated] BIT NOT NULL DEFAULT 0,
[LastRunBuild] NVARCHAR(30) NOT NULL DEFAULT 0
)
CREATE TABLE [dbo].[Result]
(
[Build] NVARCHAR(30) NOT NULL,
**[Id] INT NOT NULL,**
[SegmentId] INT NOT NULL,
[SegmentContent] text NOT NULL
PRIMARY KEY ([FileMd5Hash], [Build], [SegmentId])
)
Итак, каковы плюсы и минусы этих 2 способов?
3 ответов
ключ int проще реализовать и проще использовать и понимать. Он также меньше (4 байта против 16 байтов), поэтому индексы будут соответствовать примерно удвоенному количеству записей на странице ввода-вывода, что означает лучшую производительность. Строки таблицы тоже будут меньше (ОК, не намного меньше), поэтому вы снова поместите больше строк на страницу = меньше ввода-вывода.
хэш всегда может вызвать коллизии. Хотя и чрезвычайно редко, тем не менее, как проблема рождения показывает, столкновения становятся все более и более вероятно, по мере увеличения количества записей. Количество элементов, необходимых для 50% вероятности столкновения с различными хэшами битовой длины, выглядит следующим образом:
Hash length (bits) Item count for 50% chance of collision
32 77000
64 5.1 billion
128 22 billion billion
256 400 billion billion billion billion
существует также проблема необходимости передавать не-ascii байты-сложнее отлаживать,отправлять по проводу и т. д.
использовать int
последовательный первичные ключи для таблиц. Все остальные.
используйте ints для первичных ключей, а не хэши. Все предупреждают о хэш-коллизиях, но на практике они не являются большой проблемой; легко проверить наличие коллизий и повторного хэша. Последовательные идентификаторы также могут сталкиваться при слиянии баз данных.
большая проблема с хэшами как ключами заключается в том, что вы не можете изменить свои данные. Если вы попытаетесь, ваш хэш изменится, и все внешние ключи станут недействительными. Вы должны создать столбец" нет, это настоящий хэш " в вашей базе данных, а ваш старый хэш просто становится большой непоследовательные целое.
держу пари, ваш бизнес-аналитик скажет: "мы внедряем червя, чтобы наши записи никогда не менялись". Они окажутся неправы.
вот очень хорошая статья, объясняющая плюсы и минусы использования обоих:
http://databases.aspfaq.com/database/what-should-i-choose-for-my-primary-key.html
использование хэша MD5 будет похоже на использование GUID для вашего первичного ключа. Хэш-столкновения редки, но случаются, вы можете захотеть справиться с этим.
Я лично пойду с int IDENTITY, но он может отличаться в зависимости от вашей реализации.