私のワイルドな推測:「より効率的」とは、「チェックの実行に必要な時間が短くなる」ことを意味します(時間の利点)。「チェックを実行するために必要なメモリが少ない」ことも意味します(スペースの利点)。また、「副作用が少ない」(何かをロックしない、または短時間ロックするなど)を意味する場合もありますが、その「余分な利点」を知るまたは確認する方法がありません。
スペースの利点をチェックする簡単な方法を考えることはできません(最近のメモリが安い場合、それはそれほど重要ではないでしょう)。一方、可能な時間の利点を確認するのはそれほど難しくありません。制約を除いて、同じ2つのテーブルを作成するだけです。十分な数の行を挿入し、数回繰り返して、タイミングを確認します。
これはテーブルのセットアップです:
CREATE TABLE t1
(
id serial PRIMARY KEY,
value integer NOT NULL
) ;
CREATE TABLE t2
(
id serial PRIMARY KEY,
value integer
) ;
ALTER TABLE t2
ADD CONSTRAINT explicit_check_not_null
CHECK (value IS NOT NULL);
これは、タイミングを保存するために使用される追加のテーブルです。
CREATE TABLE timings
(
test_number integer,
table_tested integer /* 1 or 2 */,
start_time timestamp without time zone,
end_time timestamp without time zone,
PRIMARY KEY(test_number, table_tested)
) ;
そして、これはpgAdmin IIIとpgScript機能を使用して実行されたテストです。
declare @trial_number;
set @trial_number = 0;
BEGIN TRANSACTION;
while @trial_number <= 100
begin
-- TEST FOR TABLE t1
-- Insert start time
INSERT INTO timings(test_number, table_tested, start_time)
VALUES (@trial_number, 1, clock_timestamp());
-- Do the trial
INSERT INTO t1(value)
SELECT 1.0
FROM generate_series(1, 200000) ;
-- Insert end time
UPDATE timings
SET end_time=clock_timestamp()
WHERE test_number=@trial_number and table_tested = 1;
-- TEST FOR TABLE t2
-- Insert start time
INSERT INTO timings(test_number, table_tested, start_time)
VALUES (@trial_number, 2, clock_timestamp());
-- Do the trial
INSERT INTO t2(value)
SELECT 1.0
FROM generate_series(1, 200000) ;
-- Insert end time
UPDATE timings
SET end_time=clock_timestamp()
WHERE test_number=@trial_number and table_tested = 2;
-- Increase loop counter
set @trial_number = @trial_number + 1;
end
COMMIT TRANSACTION;
結果は次のクエリにまとめられています。
SELECT
table_tested,
sum(delta_time),
avg(delta_time),
min(delta_time),
max(delta_time),
stddev_pop(delta_time)
FROM
(
SELECT
table_tested, extract(epoch from (end_time - start_time)) AS delta_time
FROM
timings
) AS delta_times
GROUP BY
table_tested
ORDER BY
table_tested ;
次の結果:
table_tested | sum | min | max | avg | stddev_pop
-------------+---------+-------+-------+-------+-----------
1 | 176.740 | 1.592 | 2.280 | 1.767 | 0.08913
2 | 177.548 | 1.593 | 2.289 | 1.775 | 0.09159
値のグラフは重要な変動性を示しています。
そのため、実際には、CHECK(column IS NOT NULL)は非常にわずかに遅くなります(0.5%ずつ)。ただし、タイミングのばらつきがそれよりもはるかに大きい場合、この小さな差は任意のランダムな理由による可能性があります。したがって、統計的に有意ではありません。
実用的な観点からは、「より効率的」をあまり無視しNOT NULL
ますが、それは本当に重要だとは思わないからです。一方、がないことはAccessExclusiveLock
利点だと思います。