我的疯狂猜测:“效率更高”是指“执行检查所需的时间更少”(时间优势)。这也可能意味着“执行检查所需的内存更少”(空间优势)。这也可能意味着“副作用更少”(例如不锁定某物或在较短时间内锁定它)...但是我没有办法知道或检查“额外优势”。
我想不出一种简单的方法来检查可能的空间优势(我想,当当今的内存便宜时,这并不重要)。另一方面,检查可能的时间优势并不难:仅创建两个相同的表,唯一的例外是约束。插入足够多的行,重复几次,然后检查计时。
这是表格设置:
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(列IS NOT NULL)非常慢(降低了0.5%)。但是,这种小的差异可能是由于任何随机原因造成的,前提是时序的可变性远大于此。因此,它在统计上并不重要。
从实际的角度来看,我将非常忽略“更有效的” NOT NULL,因为我并不认为它很重要。而我认为缺少an AccessExclusiveLock是有利的。