I have a simple script.
IF OBJECT_ID('dbo.Customers', 'U') IS NOT NULL
DROP TABLE dbo.Customers;
GO
CREATE TABLE dbo.Customers
(
custid INT NOT NULL,
companyname VARCHAR(125) NOT NULL,
phone VARCHAR(120) NOT NULL,
address VARCHAR(150) NOT NULL
);
INSERT INTO dbo.Customers
(custid, companyname, phone, address)
VALUES (1, 'cust 1', '(111) 111-1111', 'address 1'),
(2, 'cust 2', '(222) 222-2222', 'address 2'),
(3, 'cust 3', '(333) 333-3333', 'address 3'),
(4, 'cust 4', '(444) 444-4444', 'address 4'),
(5, 'cust 5', '(555) 555-5555', 'address 5');
IF OBJECT_ID('dbo.CustomersStage', 'U') IS NOT NULL
DROP TABLE dbo.CustomersStage;
GO
CREATE TABLE dbo.CustomersStage
(
custid INT NOT NULL,
companyname VARCHAR(125) NOT NULL,
phone VARCHAR(120) NOT NULL,
address VARCHAR(150) NOT NULL
);
INSERT INTO dbo.CustomersStage
(custid, companyname, phone, address)
VALUES (2, 'AAAAA', '(222) 222-2222', 'address 2'),
(1, 'cust 1111111111', '(111) 111-11111111111111', 'address 111111111'),
-- (1, 'cust 1111111112222222222', '(111) 111-1111111112222222222', 'address 1111111112222222222'),
(3, 'cust 3', '(333) 333-3333', 'address 3'),
(5, 'BBBBB', 'CCCCC', 'DDDDD'),
(6, 'cust 6 (new)', '(666) 666-6666', 'address 6'),
(7, 'cust 7 (new)', '(777) 777-7777', 'address 7');
SELECT *
FROM dbo.Customers;
SELECT *
FROM dbo.CustomersStage;
SET STATISTICS XML ON;
MERGE INTO dbo.Customers d
USING dbo.CustomersStage s
ON d.custid = s.custid
WHEN MATCHED THEN
UPDATE SET d.companyname = s.companyname,
d.phone = s.phone,
d.address = s.address
WHEN NOT MATCHED THEN
INSERT (
custid,
companyname,
phone,
address
)
VALUES (
s.custid,
s.companyname,
s.phone,
s.address
);
SET STATISTICS XML OFF;
SELECT *
FROM dbo.Customers;
The execution plan of the MERGE
statement looks like this.
You can download the execution plan here at https://drive.google.com/file/d/0B4xMAUd6DN6XdkZyTmJkdF9TY3c/view?
My question is, what exactly is this [Bmk1002]? Hope someone can help to explain it.
The Table Scan operator is used to read all or most data from a table that has no clustered index (also known as a heap table, or just as a heap).
Operators describe how SQL Server executes a query or a Data Manipulation Language (DML) statement. The query optimizer uses operators to build a query plan to create the result specified in the query, or to perform the operation specified in the DML statement.
A table scan is the reading of every row in a table and is caused by queries that don't properly use indexes. Table scans on large tables take an excessive amount of time and cause performance problems.
The Table Spool operator is one of the four spool operators that SQL Server supports. It retains a copy of all data it reads in a worktable (in tempdb) and can then later return extra copies of these rows without having to call its child operators to produce them again.
It is the "bookmark" (also referred to in the phrase "bookmark lookup").
This is the physical location of the row (File:Page:Slot).
Customers is a heap
SELECT %%lockres%%
FROM Customers
Will show you these values (if it had a clustered index you could use %%physloc%%
instead but the raw output from this is not as friendly).
It is needed in this execution plan because the specification of merge requires it to throw an error if there is an attempt to update or delete the same row more than once.
As there is no other unique key available SQL Server uses this bookmark instead as a value guaranteed to be able to uniquely identify a row.
The plan calculates ROW_NUMBER() OVER (PARTITION BY Bmk1002 ORDER BY Bmk1002)
* and the assert operator raises an error if this is ever >1
(which would happen if there were multiple rows in dbo.CustomersStage that join to the same one in dbo.Customers).
* Actually the plan calls conditional_row_number
rather than row_number
. This is an internal undocumented function. I imagine that it uses the conditional version rather than straight row_number
as it needs to ignore rows with an action of "insert" in the check for duplicates.
The Bmkxxxx is an additional column, not referenced in the query. It's the key value from the tablescan and it will be used in the later parts of the query execution. Check out this excellent ebook from Red-gate to learn more about execution plans. http://download.red-gate.com/ebooks/SQL/eBOOK_SQLServerExecutionPlans_2Ed_G_Fritchey.pdf
And download this tool from SQL Sentry to help you navigate execution plans. http://www.sqlsentry.com/products/plan-explorer/sql-server-query-view
And this course at Pluralsight is excellent. https://www.pluralsight.com/courses/sqlserver-query-plan-analysis
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With