48

Tôi có một cơ sở dữ liệu rất lớn với hàng trăm bảng, và sau nhiều, nhiều nâng cấp sản phẩm, tôi chắc chắn một nửa trong số chúng không còn được sử dụng nữa. Làm thế nào tôi có thể biết một bảng đang được tích cực được chọn từ? Tôi không thể chỉ sử dụng Profiler - không chỉ tôi muốn xem trong hơn một vài ngày, mà còn có hàng nghìn thủ tục được lưu trữ, và profiler sẽ không dịch các cuộc gọi SP thành các cuộc gọi truy cập bảng. Điều duy nhất tôi có thể nghĩ đến là tạo chỉ mục nhóm trên các bảng quan tâm, sau đó theo dõi sys.dm_db_index_usage_stats để xem có bất kỳ tìm kiếm hoặc quét nào trên chỉ mục nhóm, có nghĩa là dữ liệu từ bảng đã được tải . Tuy nhiên, việc thêm chỉ mục nhóm trên mỗi bảng là một ý tưởng tồi (vì bất kỳ lý do nào), vì không thực sự khả thi.Làm cách nào để biết bảng cơ sở dữ liệu có đang được truy cập nữa không? Muốn một cái gì đó giống như một "kích hoạt SELECT"

Có tùy chọn nào khác không? Tôi đã luôn luôn muốn có một tính năng như một "kích hoạt SELECT", nhưng có lẽ có những lý do khác tại sao SQL Server không có tính năng đó hoặc.

SOLUTION:

Cảm ơn, Remus, đã chỉ cho tôi đi đúng hướng. Sử dụng các cột đó, tôi đã tạo ra SELECT sau, thực hiện chính xác những gì tôi muốn.

WITH LastActivity (ObjectID, LastAction) AS 
    (
     SELECT object_id AS TableName, 
       last_user_seek as LastAction 
     FROM sys.dm_db_index_usage_stats u 
     WHERE database_id = db_id(db_name()) 
     UNION 
     SELECT object_id AS TableName, 
       last_user_scan as LastAction 
     FROM sys.dm_db_index_usage_stats u 
     WHERE database_id = db_id(db_name()) 
     UNION 
     SELECT object_id AS TableName, 
       last_user_lookup as LastAction 
     FROM sys.dm_db_index_usage_stats u 
     WHERE database_id = db_id(db_name()) 
) 
    SELECT OBJECT_NAME(so.object_id) AS TableName, 
     MAX(la.LastAction) as LastSelect 
    FROM sys.objects so 
    LEFT 
    JOIN LastActivity la 
     on so.object_id = la.ObjectID 
    WHERE so.type = 'U' 
    AND so.object_id > 100 
GROUP BY OBJECT_NAME(so.object_id) 
ORDER BY OBJECT_NAME(so.object_id) 
+0

Có cách nào để nắm bắt dữ liệu này vào bảng khi máy chủ tắt không? Điều này sẽ cho phép theo dõi dài hạn. – AMissico

+2

Câu hỏi hay. Chỉ cần cho bất cứ ai khác nhìn vào điều này, nếu bạn đang sử dụng năm 2008, bạn có thể thay thế các truy vấn bên trong CTE với những điều sau đây; 'CHỌN object_id AS TableName, (SELECT Max (v) TỪ (VALUES (last_user_seek), (last_user_scan), (last_user_lookup)) AS giá trị (v)) như [LastAction] TỪ sys.dm_db_index_usage_stats u ĐÂU database_id = DB_ID (db_name()) ' Ví dụ từ [đây] (http://stackoverflow.com/a/6871572/685760) –

Trả lời

31

Tìm trong sys.dm_db_index_usage_stats. Các cột last_user_xxx sẽ chứa lần cuối cùng bảng được truy cập từ các yêu cầu của người dùng. Bảng này đặt lại theo dõi của nó sau khi máy chủ khởi động lại, vì vậy bạn phải để nó chạy một lúc trước khi dựa vào dữ liệu của nó.

+1

Chờ - điều này thật tuyệt vời như tôi nghĩ? Tôi sẽ làm một số thử nghiệm, nhưng nó xuất hiện mà tôi có thể theo dõi chỉ số ảo "HEAP" trên bảng cho bất kỳ tìm kiếm/quét/tra cứu, và điều đó cho tôi biết chính xác những gì tôi muốn biết. Bạn, thưa bạn, là anh hùng của tôi nếu đây là trường hợp. – SqlRyan

+0

Nó làm những gì bạn nghĩ rằng nó và nhiều hơn nữa. Bạn có thể phân biệt giữa các bảng không được sử dụng (0 heap hoặc 1 chỉ mục nhóm) và các chỉ mục không nhóm không bao giờ được sử dụng để bạn có thể loại bỏ các chỉ mục không được nhóm không cần thiết. Chỉ cần nhớ rằng nó reset khi máy chủ khởi động lại (thực sự khi một cơ sở dữ liệu trực tuyến nó reset cho db đó, chi tiết ...) –

+0

Xuất sắc. Tôi sẽ cập nhật câu hỏi bằng truy vấn ma thuật mà tôi đã phát triển bằng cách sử dụng mẹo của bạn, nhưng nó thật ngoạn mục. – SqlRyan

3

Đối với SQL Server 2008, bạn nên xem SQL Auditing. Điều này cho phép bạn kiểm tra nhiều thứ bao gồm các lựa chọn trên một bảng và báo cáo một tệp hoặc Nhật ký sự kiện.

6

Re: Profiler, nếu bạn theo dõi SP:StmtCompleted, sẽ nắm bắt tất cả các câu lệnh thực thi trong một thủ tục lưu sẵn, do đó sẽ bắt các truy cập bảng trong một sproc. Nếu không phải mọi thứ đều được thực hiện thông qua các thủ tục lưu sẵn, bạn cũng có thể cần sự kiện SQL:StmtCompleted.

Sẽ có một số lượng lớn sự kiện nên có thể vẫn không thực tế để theo dõi trong một thời gian dài do kích thước của dấu vết. Tuy nhiên, bạn có thể áp dụng bộ lọc - ví dụ: trong đó TextData chứa tên của bảng bạn muốn kiểm tra. Bạn có thể đưa ra một danh sách các tên bảng để lọc bất cứ lúc nào và làm việc thông qua chúng dần dần. Vì vậy, bạn sẽ không nhận được bất kỳ sự kiện theo dõi nếu không có bảng nào được truy cập.

Thậm chí nếu bạn cảm thấy đó không phải là cách tiếp cận phù hợp/khả thi cho bạn, tôi nghĩ rằng nó đáng để mở rộng.

Một giải pháp khác là thực hiện tìm kiếm toàn cầu mã nguồn của bạn để tìm các tham chiếu đến các bảng. Bạn có thể truy vấn các định nghĩa thủ tục được lưu trữ để kiểm tra các kết quả phù hợp cho một bảng đã cho, hoặc chỉ tạo ra một kịch bản lệnh cơ sở dữ liệu hoàn chỉnh và thực hiện Tìm kiếm trên các tên bảng.

+3

+1 cho tìm kiếm mã nguồn. Một số ứng dụng có các tính năng rất thường xuyên được sử dụng mà có thể không bao giờ bị bắt gặp bởi việc lược tả/kiểm tra. Cách duy nhất để chắc chắn là thực sự kiểm tra các chương trình sử dụng cơ sở dữ liệu! – Aaronaught

+0

Đúng. Tôi sẽ tin tưởng tìm kiếm mã nguồn nhiều hơn một chút (miễn là bạn kiểm tra TẤT CẢ mã nguồn!) Vì điều đó không liên quan đến việc theo dõi các lần truy cập thực tế trên bảng có khả năng hiếm khi/yêu cầu một thời gian dài để gắn cờ (cách bạn giám sát bao lâu?). – AdaTheDev

+0

Các ứng dụng đi ngược lại cơ sở dữ liệu này làm đủ ad-hoc SQL mà một tìm kiếm mã proc được lưu trữ sẽ không bắt tất cả mọi thứ - procs chủ yếu là có cho báo cáo và các công cụ theo lịch trình. Mặc dù vậy, tôi thích thời điểm này - tôi chưa bao giờ nhận ra sự khác biệt giữa phiên bản SP và SQL của "StmtCompleted" – SqlRyan

0

Một lưu ý phụ: nếu ý định của bạn là xóa các bảng đó, bạn có thể phải xem xét các nghĩa vụ pháp lý áp đặt nghĩa vụ đó cho bạn để giữ cho dữ liệu liên quan trong x năm.

+0

Cảm ơn ghi chú - bạn đã chính xác. Tôi nghĩ rằng lưu ý này là thích hợp hơn như là một bình luận về câu hỏi mặc dù, vì nó không phải là một câu trả lời. Chào mừng bạn đến với SO! – SqlRyan

0

tôi đã có trong tâm trí để chơi với quyền người dùng cho các bảng khác nhau, nhưng sau đó tôi nhớ bạn có thể bật dấu vết với một kích hoạt ON LOGON bạn có thể được hưởng lợi từ điều này:

CREATE OR REPLACE TRIGGER SYS.ON_LOGON_ALL 

AFTER LOGON ON DATABASE 
WHEN (

USER 'MAX' 

) 
BEGIN 

EXECUTE IMMEDIATE 'ALTER SESSION SET SQL_TRACE TRUE'; 

--EXECUTE IMMEDIATE 'alter session set events ''10046 trace name context forever level 12'''; 

EXCEPTION 

WHEN OTHERS THEN 

NULL; 

END; 

/

Sau đó, bạn có thể kiểm tra dấu vết của bạn các tập tin.

+1

Đây là truy vấn Oracle; nó sẽ không hoạt động trên SQL Server. –

-1

Giải pháp này hoạt động tốt hơn cho tôi rồi giải pháp ở trên. Tuy nhiên, vẫn còn hạn chế rằng máy chủ không được bắt đầu lại, nhưng vẫn cung cấp cho bạn một ý tưởng tốt về các bảng không được sử dụng.

SELECT [name] 
     ,[object_id] 
     ,[principal_id] 
     ,[schema_id] 
     ,[parent_object_id] 
     ,[type] 
     ,[type_desc] 
     ,[create_date] 
     ,[modify_date] 
     ,[is_ms_shipped] 
     ,[is_published] 
     ,[is_schema_published] 
    FROM [COMTrans].[sys].[all_objects] 
    where object_id not in (
select object_id from sys.dm_db_index_usage_stats 

) 
and type='U' 
order by name 
+0

Điều này không cung cấp dữ liệu hoạt động, chỉ là danh sách các bảng có thông tin DDL. – rainabba

Các vấn đề liên quan