Натуральные ключи отличаются от суррогатных ключей значением, а не типом.
Любой тип может использоваться для суррогатного ключа, например VARCHAR
для сгенерированного системой slug
или что-то еще.
Однако, чаще всего используются типы суррогатных ключей INTEGER
и RAW(16)
(или любой тип, который ваш RDBMS
использует для GUID
),
Сравнение суррогатных чисел и натуральных целых чисел (например, SSN
) занимает ровно столько же времени.
Сравнение VARCHAR
s учитывает параметры сортировки, и они обычно длиннее целых, что делает их менее эффективными.
Сравнение набора из двух INTEGER
, вероятно, также менее эффективно, чем сравнение одного INTEGER
.
Для небольших типов данных эта разница, вероятно, составляет процентов от процентов времени, необходимого для выборки страниц, обхода индексов, защелкивания базы данных и т. Д.
А вот цифры (в MySQL
):
CREATE TABLE aint (id INT NOT NULL PRIMARY KEY, value VARCHAR(100));
CREATE TABLE adouble (id1 INT NOT NULL, id2 INT NOT NULL, value VARCHAR(100), PRIMARY KEY (id1, id2));
CREATE TABLE bint (id INT NOT NULL PRIMARY KEY, aid INT NOT NULL);
CREATE TABLE bdouble (id INT NOT NULL PRIMARY KEY, aid1 INT NOT NULL, aid2 INT NOT NULL);
INSERT
INTO aint
SELECT id, RPAD('', FLOOR(RAND(20090804) * 100), '*')
FROM t_source;
INSERT
INTO bint
SELECT id, id
FROM aint;
INSERT
INTO adouble
SELECT id, id, value
FROM aint;
INSERT
INTO bdouble
SELECT id, id, id
FROM aint;
SELECT SUM(LENGTH(value))
FROM bint b
JOIN aint a
ON a.id = b.aid;
SELECT SUM(LENGTH(value))
FROM bdouble b
JOIN adouble a
ON (a.id1, a.id2) = (b.aid1, b.aid2);
t_source
- это просто фиктивная таблица с 1,000,000
строками.
aint
и adouble
, bint
и bdouble
содержат точно такие же данные, за исключением того, что aint
имеет целое число как PRIMARY KEY
, тогда как adouble
имеет пару из двух одинаковых целых чисел.
На моем компьютере оба запроса выполняются в течение 14,5 секунд, +/- 0,1 секунды
Разница в производительности, если таковая имеется, находится в пределах диапазона колебаний.