Tìm các thủ tục được lưu trữ với các chỉ mục bị thiếu


7

Làm thế nào để quét các Proc được lưu trữ cần lập chỉ mục.

Bất cứ ai có ý tưởng? Về cơ bản chúng tôi đã lưu trữ các thủ tục chạy rất chậm. Tôi đang tự hỏi liệu có một loại tập lệnh hoặc ứng dụng tự động nào có thể quét để cho biết liệu chỉ mục có cần được tạo không?


1
Phiên bản SQL Server nào bạn đang sử dụng?
Aaron Bertrand

Câu trả lời:


7

Chưa suy nghĩ nhiều về vấn đề này và chỉ trả lời câu hỏi cụ thể, đây là một cách để xác định tất cả các quy trình được lưu trữ mà các bảng tham chiếu có lúc được xác định là ứng cử viên cho các chỉ mục bổ sung. Thật không may, đây là một mối quan hệ rất lỏng lẻo ... Tôi không tin có bất kỳ cách đơn giản nào để nói "quy trình được lưu trữ này đã truy vấn bảng này và có thể đã sử dụng chỉ mục được đề xuất này" trừ khi bạn bắt đầu phân tích văn bản sql và kết hợp mờ với các cột vv được đề xuất bởi các DMV chỉ số bị thiếu. Đây là một sự khởi đầuđối với quá trình đó. Điều đó nói rằng, tôi đồng ý với Henry, có rất nhiều cách trực tiếp hơn để phân tích và giải quyết các vấn đề về hiệu suất trong các quy trình được lưu trữ mà bạn đã xác định. Việc xem xét kế hoạch thực hiện, chẳng hạn, sẽ cung cấp một số manh mối trực quan hơn nhiều so với phương pháp vòng quanh này mà bạn muốn theo đuổi. Trong mọi trường hợp, đây là một truy vấn để bắt đầu bạn:

SELECT 
  [Procedure] = QUOTENAME(OBJECT_SCHEMA_NAME(s.[object_id])) 
        + '.' + QUOTENAME(OBJECT_NAME(s.[object_id])), 
  [Table]     = QUOTENAME(r.referenced_schema_name) 
        + '.' + QUOTENAME(r.referenced_entity_name),
  i.equality_columns, 
  i.inequality_columns,
  i.included_columns,
  s.execution_count,
  avg_time = s.total_elapsed_time*1.0/s.execution_count
FROM sys.dm_exec_procedure_stats AS s
CROSS APPLY sys.dm_sql_referenced_entities
(
  QUOTENAME(OBJECT_SCHEMA_NAME(s.[object_id]))
  + '.' + QUOTENAME(OBJECT_NAME(s.[object_id])), 'OBJECT'
) AS r
INNER JOIN sys.dm_db_missing_index_details AS i
ON i.[object_id] = r.referenced_id
WHERE r.referenced_minor_id = 0;

Lưu ý: DMV thường chỉ có dữ liệu kể từ lần khởi động lại cuối cùng.


4

Bắt đầu với SS 2005, có một DMV được gọi là sys.dm_db_missing_index_details. Google và bạn sẽ tìm thấy một số tập lệnh hữu ích.

Điều đó nói rằng, bạn có thể cần xem xét vấn đề một cách toàn diện hơn - phần cứng của bạn có đầy đủ không (bộ đếm Perfmon sẽ giúp bạn điều này), còn gì nữa đang chạy cùng lúc, SQL đang chờ đợi điều gì (Google DMV sys.dm_os_wait_stats cho một số kịch bản tuyệt vời). Và bạn có thể nhìn vào kế hoạch thực hiện của thủ tục được lưu trữ cụ thể để tìm ra nơi tắc nghẽn.


0

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ố" 290425, xuất hiện lần lượt là 2x và 3x.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.