Short and Lousy
This is one of the most frustrating things I’ve seen from the optimizer in quite a while.
Here are a couple tables, with a foreign key between them:
CREATE TABLE dbo.ct(id int PRIMARY KEY, dt datetime);
CREATE TABLE dbo.ct_fk(id int PRIMARY KEY, dt datetime);
ALTER TABLE dbo.ct ADD CONSTRAINT
ct_c_fk FOREIGN KEY (id) REFERENCES dbo.ct_fk(id);
When we use the EXISTS clause, join elimination occurs normally:
SELECT COUNT_BIG(*) AS [?]
FROM dbo.ct AS c
WHERE EXISTS
(
SELECT 1/0
FROM dbo.ct_fk AS cf
WHERE cf.id = c.id
);

But when we use NOT EXISTS, it… doesn’t.
SELECT COUNT_BIG(*) AS [?]
FROM dbo.ct AS c
WHERE NOT EXISTS
(
SELECT 1/0
FROM dbo.ct_fk AS cf
WHERE cf.id = c.id
);

Thanks for reading!
Going Further
If this is the kind of SQL Server stuff you love learning about: these days I have AI do the annoying stuff for me. My new video course teaches you to work the same way, and I teach whole teams in a one-day workshop. Someone still has to know enough SQL Server to keep the robots in check, and that’s what my training is for.
Related Posts
- SQL Server 2017 CU 30: The Real Story With SelOnSeqPrj Fixes
- Getting The Top Value Per Group With Multiple Conditions In SQL Server: Row Number vs. Cross Apply With MAX
- Getting The Top Value Per Group In SQL Server: Row Number vs. Cross Apply Performance
- Multiple Distinct Aggregates: Still Harm Performance Without Batch Mode In SQL Server
One thought on “SQL Server Foreign Keys Don’t Always Improve Query Plans”
Comments are closed.