SQL Server 2008 R2 - Enterprise Edition
Step 1.Create session
IF EXISTS(SELECT * FROM sys.server_event_sessions WHERE name='SQLStmtEvents')
DROP EVENT session SQLStmtEvents ON SERVER;
GO
CREATE EVENT SESSION SQLStmtEvents
ON SERVER
ADD EVENT sqlserver.sql_statement_completed
(ACTION (sqlserver.client_app_name,sqlserver.plan_handle,sqlserver.sql_text,sqlserver.tsql_stack,package0.callstack,sqlserver.request_id)
WHERE sqlserver.database_id=8 --set AdventureWorks2008 DB_ID()
)
ADD target package0.ring_buffer
GO
WITH (MAX_DISPATCH_LATENCY=5SECONDS, TRACK_CAUSALITY=ON)
USE AdventureWorks2008;
GO
Step 2. Start session and insert 1 row
ALTER EVENT SESSION SQLStmtEvents ON SERVER STATE = START;
GO
INSERT INTO [dbo].[ErrorLog]([ErrorTime],[UserName],[ErrorNumber],[ErrorSeverity],[ErrorState],[ErrorProcedure],[ErrorLine],[ErrorMessage])
VALUES(getdate(),SYSTEM_USER,-1,-1,-1,'ErrorProcedure, nvarchar(126)',-1,'ErrorMessage, nvarchar(4000)')
Step 3. Retrieve session xml
SELECT CAST(target_data AS XML) AS TargetData
FROM sys.dm_xe_session_targets st
JOIN sys.dm_xe_sessions s
ON s.address = st.event_session_address
WHERE name = 'SQLStmtEvents'
AND target_name = 'ring_buffer'
Step 4. Find insert plan handler and put it in sys.dm_exec_query_plan. It returns nothing
select * from sys.dm_exec_query_plan(0x06000800DD8D6D0840015585000000000000000000000000) --replace this value with plan_handle value
It produce the following fragment in event:
<action name="client_app_name" package="sqlserver">
<type name="unicode_string" package="package0" />
<value>Microsoft SQL Server Management Studio - Query</value>
<text />
</action>
<action name="plan_handle" package="sqlserver">
<type name="unicode_string" package="package0" />
<value><plan handle='0x06000800F9DD170540010187000000000000000000000000'/></value>
<text />
</action>
<action name="sql_text" package="sqlserver">
<type name="unicode_string" package="package0" />
<value>INSERT INTO [dbo].[ErrorLog]([ErrorTime],[UserName],[ErrorNumber],[ErrorSeverity],[ErrorState],[ErrorProcedure],[ErrorLine],[ErrorMessage])
VALUES(getdate(),SYSTEM_USER,-1,-1,-1,'ErrorProcedure, nvarchar(126)',-1,'ErrorMessage, nvarchar(4000)')
</value>
<text />
</action>
Here I can see insert event with plan_handle action. When I try to use that handle it returns nothing:
select query_plan from sys.dm_exec_query_plan(0x06000800F9DD170540010187000000000000000000000000)
Why EE generates that dummy plan handle for insert statements? Instead of statement plan it uses cluster index plan. That is understandable. But that plan handle chain (event session->query cache->index cache) is broken. And my task is to retrieve application name which insert data in tables. Without event session I don't know which application associated with cached query. Without statement query plan I can't match insert statemtns with spesific application.
Instead of generating dummy plan handle for insert statement I would like to see handle for cluster index plan. Otherwise I have to scan it in really havy manner with unacceptable perfomance:
;WITH XMLNAMESPACES(DEFAULT N'http://schemas.microsoft.com/sqlserver/2004/07/showplan')
,index_plans as(
select qp.query_plan, st.text
FROM sys.dm_exec_cached_plans cp
CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st
CROSS APPLY sys.dm_exec_query_plan(cp.plan_handle) qp
CROSS APPLY qp.query_plan.nodes(N'//RelOp') RelOp (op)
where cp.cacheobjtype = N'Compiled Plan' and RelOp.op.value(N'@LogicalOp', N'varchar(50)') = 'Insert'
)
update myplans set myplans.query_plan = index_plans.query_plan
from #my_eventsession_plans myplans
inner join index_plans on index_plans.text like '%'+myplans.sql_text
where myplans.sql_text like '%insert%into%' and myplans.query_plan is null