Unusual column comparisons and query performance
6
votes
2
answers
683
views
We have some consultants working on expanding an inhouse data warehouse. I was doing a code review and ran across this pattern in all of the load procs:
MERGE [EDHub].[Customer].[Class] AS TARGET
USING (
SELECT
FROM [dbo].[vw_CustomerClass]
WHERE JHAPostingDate = @PostingDate
) AS SOURCE
ON TARGET.BankId = SOURCE.BankId -- This join is on the business keys
AND TARGET.Code = SOURCE.Code
WHEN NOT MATCHED BY TARGET
THEN
WHEN MATCHED
AND TARGET.IsLatest = 1
AND EXISTS (
SELECT SOURCE.[HASH]
EXCEPT
SELECT TARGET.[Hash]
)
THEN
The gist is, if we have a new business key, insert but if the business key exists and the hash of the attributes don't match our current row then update the old row and insert a new one (later in the code). It all works fine but I paused when I got to this code
AND EXISTS (
SELECT SOURCE.[HASH]
EXCEPT
SELECT TARGET.[Hash]
)
It seems overly complicated compared to SOURCE.[HASH] TARGET.[Hash]. The EXCEPT will do an accurate NULL comparison but in our case hashes will never be NULL (or we have bigger problems). I want our code to be easy to read so that when someone has to maintain it, it doesn't confuse. I asked our consultants about it and they speculated that it might be faster because of set operations but I decided to write a simple test (test code below).
The first thing I noticed was the EXISTS/EXCEPT had a more complicated query plan but that's not always bad
I ran each select client statistics on and the join yielded total execution time of 12,000 vs 25,000 with the EXISTS/EXCEPT. I want to take this to our consultants with the request to refactor that statement but wanted to get feedback here on:
1. is this a good test? - am I missing anything?
2. is there a case where EXISTS/EXCEPT would be a better comparison?
Test script:
CREATE TABLE r (hash VARBINARY(8000))
CREATE TABLE l (hash VARBINARY(8000))
SET NOCOUNT ON
DECLARE @x INT = 10000
WHILE @x 0 BEGIN
INSERT INTO dbo.r ( hash ) SELECT HASHBYTES('SHA2_256',CAST(NEWID() AS VARCHAR(200)))
INSERT INTO dbo.l ( hash ) SELECT HASHBYTES('SHA2_256',CAST(NEWID() AS VARCHAR(200)))
SET @x = @x-1
END
INSERT INTO dbo.r ( hash ) VALUES ( NULL )
INSERT INTO dbo.l ( hash ) VALUES ( NULL )
SELECT COUNT(1)
FROM dbo.l
CROSS JOIN dbo.r
WHERE ISNULL(r.hash,0) ISNULL(l.hash,0)
SELECT COUNT(1)
FROM dbo.l
CROSS JOIN dbo.r
WHERE EXISTS(SELECT r.hash except select l.HASH)
Asked by Bob Probst
(267 rep)
Apr 15, 2018, 03:32 PM
Last activity: Dec 31, 2024, 09:01 AM
Last activity: Dec 31, 2024, 09:01 AM