Trả lời bài đăng của @Aaron Bertrand bằng cách thêm vào tối ưu hóa chỉ mục truy vấn chung (và tự động tạo DDL cho các chỉ báo mới) theo câu trả lời của @ Rory tại đây: https://stackoverflow.com/a/26060183/4228193 :
sp_updatestats
go
SELECT
CONVERT (decimal (28,1), (
migs.avg_total_user_cost * migs.avg_user_impact * (migs.user_seeks + migs.user_scans) +
migs.avg_total_system_cost * migs.avg_system_impact * (migs.system_seeks + migs.system_scans) +
COALESCE(SPs.total_elapsed_time*1.0/
290/ --based on 'SELECT total_elapsed_time/(DATEDIFF(second, start_time, GETDATE())+1.0) FROM sys.dm_exec_requests' for my personal install of SQL Server
1000/ --otherwise seems closer to ms; total seconds of execution to get here
425 -- the approximate relationship between avg_total_user_cost and the average of total_elapsed_time for a stored procedure on my system
, 0) * (migs.avg_user_impact + migs.avg_system_impact)
)) AS improvement_measure,
COALESCE(QUOTENAME(DB_NAME(SPs.database_id))+'.','') +
COALESCE(QUOTENAME(OBJECT_SCHEMA_NAME(SPs.[object_id]))+'.','') +
COALESCE(QUOTENAME(OBJECT_NAME(SPs.[object_id])),CAST(SPs.[object_id] as nvarchar(128)),'N/A') as [ProcedureAppliesTo],
' CREATE INDEX
[missing_index_' + CONVERT(varchar, mig.index_group_handle) + '_' + CONVERT(varchar, mid.index_handle) + ']
ON ' + mid.statement + '
(' + ISNULL (mid.equality_columns,'') +
CASE WHEN mid.equality_columns IS NOT NULL
AND mid.inequality_columns IS NOT NULL
THEN ','
ELSE ''
END +
ISNULL(mid.inequality_columns, '') + '
)' +
ISNULL(' INCLUDE (' + mid.included_columns + ')', '') as [create_index_statement],
COALESCE(QUOTENAME(SPs.referenced_schema_name)+'.',QUOTENAME(OBJECT_SCHEMA_NAME(mid.object_id))+'.','') +
COALESCE(QUOTENAME(SPs.referenced_entity_name),QUOTENAME(OBJECT_NAME(mid.object_id)),'') as [TableName],
SPs.exec_count,
SPs.total_elapsed_time*1.0/
290/ --based onselect total_elapsed_time/(DATEDIFF(second, start_time, GETDATE())+1.0) from sys.dm_exec_requests
1000/ --otherwise seems closer to ms
SPs.exec_count as [avg_time_sp],
SPs.total_elapsed_time*1.0/
290/ --based onselect total_elapsed_time/(DATEDIFF(second, start_time, GETDATE())+1.0) from sys.dm_exec_requests
1000/ --otherwise seems closer to ms
SPs.exec_count/
425 as avg_total_user_cost_sp,
SPs.cacheobjtype,
SPs.objtype,
CASE WHEN migs.last_user_seek>migs.last_system_seek THEN migs.last_user_seek ELSE COALESCE(migs.last_system_seek,migs.last_user_seek) END as last_seek,
CASE WHEN migs.last_user_scan>migs.last_system_scan THEN migs.last_user_scan ELSE COALESCE(migs.last_system_scan,migs.last_user_scan) END as last_scan,
SPs.last_execution_timestamp,
CONVERT(varchar, getdate(), 121) AS this_query_time_of_exec
FROM
sys.dm_db_missing_index_details AS mid
INNER JOIN sys.dm_db_missing_index_groups AS mig
ON mig.index_handle = mid.index_handle
INNER JOIN sys.dm_db_missing_index_group_stats as migs
ON migs.group_handle = mig.index_group_handle
LEFT JOIN (
SELECT
CASE WHEN SUM(eps.execution_count)>=SUM(cp.usecounts) THEN SUM(eps.execution_count) ELSE COALESCE(SUM(cp.usecounts),SUM(eps.execution_count)) END as exec_count,
SUM(eps.total_elapsed_time) as total_elapsed_time,
MAX(cp.cacheobjtype) as cacheobjtype,
MAX(cp.objtype) as objtype,
MAX(eps.last_execution_time) as last_execution_timestamp,
re.referenced_entity_name,
re.referenced_schema_name,
re.referenced_id,
eps.database_id,
eps.[object_id]
FROM
sys.dm_exec_procedure_stats AS eps
INNER JOIN sys.dm_exec_cached_plans as cp
ON cp.plan_handle=eps.plan_handle
CROSS APPLY sys.dm_sql_referenced_entities (
COALESCE(QUOTENAME(OBJECT_SCHEMA_NAME(eps.[object_id]))+'.','') +
COALESCE(QUOTENAME(OBJECT_NAME(eps.[object_id])),CAST(eps.[object_id] as nvarchar(128)),''),
'OBJECT'
) AS re
GROUP BY
re.referenced_entity_name,
re.referenced_schema_name,
re.referenced_id,
eps.database_id,
eps.[object_id]
) as SPs
ON mid.[object_id] = SPs.referenced_id
Tùy thuộc vào chi tiết cụ thể của bản cài đặt SQL của bạn, bạn có thể phải điều chỉnh "hằng số" 290
và 425
, xuất hiện lần lượt là 2x và 3x.