Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Cách cập nhật thống kê máy chủ SQL cho bảng lớn

Trong bài viết trước, tôi đã trình bày ngắn gọn về số liệu thống kê cơ sở dữ liệu, tầm quan trọng của nó và lý do tại sao số liệu thống kê nên được cập nhật. Hơn nữa, tôi đã chứng minh quy trình từng bước để tạo kế hoạch bảo trì SQL Server để cập nhật số liệu thống kê. Trong bài viết này, các vấn đề sau sẽ được giải thích:1. Cách cập nhật số liệu thống kê bằng T-SQL Command. 2. Cách xác định các bảng được cập nhật thường xuyên bằng T-SQL và cả cách cập nhật thống kê các bảng có dữ liệu được chèn / cập nhật / xóa thường xuyên.

Cập nhật thống kê bằng T-SQL

Bạn có thể cập nhật số liệu thống kê bằng cách sử dụng tập lệnh T-SQL. Nếu bạn muốn cập nhật thống kê bằng cách sử dụng studio quản lý T-SQL hoặc SQL Server, bạn cần có cơ sở dữ liệu ALTER quyền trên cơ sở dữ liệu. Xem ví dụ về mã T-SQL để cập nhật thống kê của một bảng cụ thể:

UPDATE STATISTICS <schema_name>.<table_name>.

Chúng ta hãy xem xét ví dụ về việc cập nhật thống kê của OrderLines bảng WideWorldImporters cơ sở dữ liệu. Tập lệnh sau sẽ thực hiện điều đó.

UPDATE STATISTICS [Sales].[OrderLines]

Nếu bạn muốn cập nhật thống kê của một chỉ mục cụ thể, bạn có thể sử dụng tập lệnh sau:

UPDATE STATISTICS <schema_name>.<table_name> <index_name>

Trong trường hợp bạn muốn cập nhật thống kê của IX_Sales_OrderLines_Perf_20160301_02 chỉ mục của Dòng đặt hàng bảng, bạn có thể thực thi tập lệnh sau:

UPDATE STATISTICS [Sales].[OrderLines] [IX_Sales_OrderLines_Perf_20160301_02]

Bạn cũng có thể cập nhật số liệu thống kê của toàn bộ cơ sở dữ liệu. Nếu bạn có một cơ sở dữ liệu rất nhỏ với ít bảng và ít dữ liệu, thì bạn có thể cập nhật thống kê của tất cả các bảng trong cơ sở dữ liệu. Xem tập lệnh sau:

USE wideworldimporters 
go 
EXEC Sp_updatestats

Cập nhật thống kê cho các bảng có dữ liệu được chèn / cập nhật / xóa thường xuyên

Trên cơ sở dữ liệu lớn, việc lập lịch biểu cho công việc thống kê trở nên phức tạp, đặc biệt khi bạn chỉ có vài giờ để thực hiện bảo trì chỉ mục, cập nhật thống kê và hoàn thành các nhiệm vụ bảo trì khác. Bởi một cơ sở dữ liệu lớn, ý tôi là một cơ sở dữ liệu chứa hàng nghìn bảng và mỗi bảng chứa hàng nghìn hàng. Ví dụ, chúng ta có một cơ sở dữ liệu tên X. Nó có hàng trăm bảng và mỗi bảng có hàng triệu hàng. Và chỉ một số bảng được cập nhật thường xuyên. Các bảng khác hiếm khi bị thay đổi và có rất ít giao dịch được thực hiện trên chúng. Như tôi đã đề cập trước đây, để giữ cho hiệu suất cơ sở dữ liệu luôn đạt chuẩn, thống kê bảng phải được cập nhật. Vì vậy, chúng tôi tạo một kế hoạch bảo trì SQL để cập nhật thống kê của tất cả các bảng trong cơ sở dữ liệu X. Khi máy chủ SQL cập nhật số liệu thống kê của một bảng, nó sử dụng một lượng lớn tài nguyên có thể dẫn đến sự cố về hiệu suất. Vì vậy, phải mất nhiều thời gian để cập nhật số liệu thống kê của hàng trăm bảng lớn và trong khi số liệu thống kê đang được cập nhật, hiệu suất của cơ sở dữ liệu giảm đáng kể. Trong những trường hợp như vậy, chỉ nên cập nhật số liệu thống kê cho những bảng được cập nhật thường xuyên. Bạn có thể theo dõi những thay đổi về khối lượng dữ liệu hoặc số lượng hàng theo thời gian bằng cách sử dụng các chế độ xem quản lý động sau:1. sys.partitions cung cấp thông tin về tổng số hàng trong bảng. 2. sys.dm_db_partition_stats cung cấp thông tin về số lượng hàng và số lượng trang, trên mỗi phân vùng. 3. sys.dm_db_index_physical_stats cung cấp thông tin về số hàng và số trang, cùng với thông tin về phân mảnh chỉ mục và hơn thế nữa. Các chi tiết về khối lượng dữ liệu là quan trọng, nhưng chúng không làm cho bức tranh về hoạt động cơ sở dữ liệu trở nên hoàn chỉnh. Ví dụ, một bảng dàn có số lượng bản ghi gần bằng nhau có thể bị xóa khỏi bảng hoặc chèn vào bảng mỗi ngày. Do đó, một ảnh chụp nhanh về số hàng sẽ gợi ý rằng bảng là tĩnh. Có thể các bản ghi được thêm vào và bị xóa có các giá trị rất khác nhau làm thay đổi nhiều phân phối dữ liệu. Trong trường hợp này, việc tự động cập nhật số liệu thống kê trong SQL Server làm cho số liệu thống kê trở nên vô nghĩa. Do đó, theo dõi số lượng sửa đổi đối với một bảng là rất hữu ích. Điều này có thể được thực hiện theo những cách sau:1. rowmodctr cột trong sys.sysindexes 2. mod_count trong sys.system_internals_partition_columns 3. modification_counter cột trong sys.dm_db_stats_properties Do đó, như tôi đã giải thích trước đó, nếu bạn có thời gian giới hạn để bảo trì cơ sở dữ liệu, thì bạn nên cập nhật thống kê chỉ cho các bảng có tần suất thay đổi dữ liệu cao hơn (chèn / cập nhật / xóa). Để làm điều đó một cách hiệu quả, tôi đã tạo một tập lệnh cập nhật số liệu thống kê cho các bảng "đang hoạt động". Tập lệnh thực hiện các tác vụ sau:• Khai báo các tham số cần thiết • Tạo bảng tạm thời có tên #tempstosystem để lưu trữ tên bảng, tên lược đồ và tên cơ sở dữ liệu • Tạo một bảng khác có tên #tempdatabase để lưu tên cơ sở dữ liệu. Đầu tiên, hãy thực thi tập lệnh sau để tạo hai bảng:

DECLARE @databasename VARCHAR(500) 
DECLARE @i INT=0 
DECLARE @DBCOunt INT 
DECLARE @SQLCOmmand NVARCHAR(max) 
DECLARE @StatsUpdateCOmmand NVARCHAR(max) 

CREATE TABLE #tempstatistics 
  ( 
     databasename VARCHAR(max), 
     tablename    VARCHAR(max), 
     schemaname   VARCHAR(max) 
  ) 

CREATE TABLE #tempdatabases 
  ( 
     databasename VARCHAR(max) 
  ) 

INSERT INTO #tempdatabases 
            (databasename) 
SELECT NAME 
FROM   sys.databases 
WHERE  database_id > 4 
ORDER  BY NAME

Tiếp theo, viết vòng lặp while để tạo truy vấn SQL động lặp qua tất cả cơ sở dữ liệu và chèn danh sách các bảng có bộ đếm sửa đổi lớn hơn 200 vào #tempstosystem bàn. Để nhận thông tin về các thay đổi dữ liệu, tôi sử dụng sys.dm_db_stats_properties . Nghiên cứu ví dụ mã sau:

SET @DBCOunt=(SELECT Count(*) 
                    FROM   #tempdatabases) 
      WHILE ( @i < @DBCOunt ) 
        BEGIN 
            DECLARE @DBName VARCHAR(max) 
            SET @DBName=(SELECT TOP 1 databasename 
                         FROM   #tempdatabases) 
            SET @SQLCOmmand= '     use [' + @DBName + '];     select 
distinct ''' + @DBName+ ''', a.TableName,a.SchemaName from (SELECT obj.name as TableName, b.name as SchemaName,obj.object_id, stat.name, stat.stats_id, last_updated, modification_counter       FROM [' + @DBName+ '].sys.objects AS obj     inner join ['+ @DBName + '].sys.schemas b on obj.schema_id=b.schema_id   INNER JOIN [' + @DBName+ '].sys.stats AS stat ON stat.object_id = obj.object_id    CROSS APPLY [' + @DBName+'].sys.dm_db_stats_properties(stat.object_id, stat.stats_id) AS sp WHERE modification_counter > 200 and obj.name not like ''sys%''and b.name not like 
''sys%'')a' 
    INSERT INTO #tempstatistics 
                (databasename, 
                 tablename, 
                 schemaname) 
    EXEC Sp_executesql 
      @SQLCOmmand

Bây giờ, tạo vòng lặp thứ hai trong vòng lặp đầu tiên. Nó sẽ tạo ra một Truy vấn SQL động cập nhật các số liệu thống kê với quá trình quét toàn bộ. Xem ví dụ mã bên dưới:

DECLARE @j INT=0 
    DECLARE @StatCount INT 

    SET @StatCount =(SELECT Count(*) 
                     FROM   #tempstatistics) 

    WHILE @J < @StatCount 
      BEGIN 
          DECLARE @DatabaseName_Stats VARCHAR(max) 
          DECLARE @Table_Stats VARCHAR(max) 
          DECLARE @Schema_Stats VARCHAR(max) 
          DECLARE @StatUpdateCommand NVARCHAR(max) 

          SET @DatabaseName_Stats=(SELECT TOP 1 databasename 
                                   FROM   #tempstatistics) 
          SET @Table_Stats=(SELECT TOP 1 tablename 
                            FROM   #tempstatistics) 
          SET @Schema_Stats=(SELECT TOP 1 schemaname 
                             FROM   #tempstatistics) 
          SET @StatUpdateCommand='Update Statistics [' + @DatabaseName_Stats 
                                 + '].[' + @Schema_Stats + '].[' + @Table_Stats 
                                 + '] with fullscan' 
          EXEC Sp_executesql 
            @StatUpdateCommand 
          SET @[email protected] + 1 
          DELETE FROM #tempstatistics 
          WHERE  databasename = @DatabaseName_Stats 
                 AND tablename = @Table_Stats 
                 AND schemaname = @Schema_Stats 
      END 
    SET @[email protected] + 1 
    DELETE FROM #tempdatabases 
    WHERE  databasename = @DBName 
END

Sau khi hoàn tất quá trình thực thi tập lệnh, nó sẽ xóa tất cả các bảng tạm thời.

SELECT * 
    FROM   #tempstatistics 
    DROP TABLE #tempdatabases 
    DROP TABLE #tempstatistics

Toàn bộ tập lệnh sẽ xuất hiện như sau:

--set count on     
CREATE PROCEDURE Statistics_maintenance 
AS 
  BEGIN 
      DECLARE @databasename VARCHAR(500) 
      DECLARE @i INT=0 
      DECLARE @DBCOunt INT 
      DECLARE @SQLCOmmand NVARCHAR(max) 
      DECLARE @StatsUpdateCOmmand NVARCHAR(max) 
      CREATE TABLE #tempstatistics 
        ( 
           databasename VARCHAR(max), 
           tablename    VARCHAR(max), 
           schemaname   VARCHAR(max) 
        ) 
      CREATE TABLE #tempdatabases 
        ( 
           databasename VARCHAR(max) 
        ) 
      INSERT INTO #tempdatabases 
                  (databasename) 
      SELECT NAME 
      FROM   sys.databases 
      WHERE  database_id > 4  
      ORDER  BY NAME 
      SET @DBCOunt=(SELECT Count(*) 
                    FROM   #tempdatabases) 
      WHILE ( @i < @DBCOunt ) 
        BEGIN 
            DECLARE @DBName VARCHAR(max) 
            SET @DBName=(SELECT TOP 1 databasename 
                         FROM   #tempdatabases) 
            SET @SQLCOmmand= '     use [' + @DBName + '];     select 
distinct ''' + @DBName+ ''', a.TableName,a.SchemaName from (SELECT obj.name as TableName, b.name as SchemaName,obj.object_id, stat.name, stat.stats_id, last_updated, modification_counter       FROM [' + @DBName+ '].sys.objects AS obj     inner join ['+ @DBName + '].sys.schemas b on obj.schema_id=b.schema_id   INNER JOIN [' + @DBName+ '].sys.stats AS stat ON stat.object_id = obj.object_id    CROSS APPLY [' + @DBName+'].sys.dm_db_stats_properties(stat.object_id, stat.stats_id) AS sp WHERE modification_counter > 200 and obj.name not like ''sys%''and b.name not like 
''sys%'')a' 
    INSERT INTO #tempstatistics 
                (databasename, 
                 tablename, 
                 schemaname) 
    EXEC Sp_executesql 
      @SQLCOmmand 

    DECLARE @j INT=0 
    DECLARE @StatCount INT 

    SET @StatCount =(SELECT Count(*) 
                     FROM   #tempstatistics) 

    WHILE @J < @StatCount 
      BEGIN 
          DECLARE @DatabaseName_Stats VARCHAR(max) 
          DECLARE @Table_Stats VARCHAR(max) 
          DECLARE @Schema_Stats VARCHAR(max) 
          DECLARE @StatUpdateCommand NVARCHAR(max) 

          SET @DatabaseName_Stats=(SELECT TOP 1 databasename 
                                   FROM   #tempstatistics) 
          SET @Table_Stats=(SELECT TOP 1 tablename 
                            FROM   #tempstatistics) 
          SET @Schema_Stats=(SELECT TOP 1 schemaname 
                             FROM   #tempstatistics) 
          SET @StatUpdateCommand='Update Statistics [' + @DatabaseName_Stats 
                                 + '].[' + @Schema_Stats + '].[' + @Table_Stats 
                                 + '] with fullscan' 
          EXEC Sp_executesql 
            @StatUpdateCommand 
          SET @[email protected] + 1 
          DELETE FROM #tempstatistics 
          WHERE  databasename = @DatabaseName_Stats 
                 AND tablename = @Table_Stats 
                 AND schemaname = @Schema_Stats 
      END 
    SET @[email protected] + 1 
    DELETE FROM #tempdatabases 
    WHERE  databasename = @DBName 
END 
    SELECT * 
    FROM   #tempstatistics 
    DROP TABLE #tempdatabases 
    DROP TABLE #tempstatistics 
END

Bạn cũng có thể tự động hóa tập lệnh này bằng cách tạo một công việc SQL Server Agent sẽ thực thi nó vào một thời điểm đã lên lịch. Dưới đây là hướng dẫn từng bước để tự động hóa công việc này.

Tạo công việc SQL

Đầu tiên, hãy tạo một SQL Job để tự động hóa quy trình. Để làm điều đó, hãy mở SSMS, kết nối với máy chủ mong muốn và mở rộng SQL Server Agent, nhấp chuột phải vào Công việc và chọn Công việc mới . Trong Công việc mới hộp thoại, nhập tên mong muốn trong Tên đồng ruộng. Bây giờ, nhấp vào Các bước tùy chọn trình đơn trên bảng điều khiển bên trái của Công việc mới hộp thoại, sau đó nhấp vào Mới trong Các bước cửa sổ. Trong Bước công việc mới hộp thoại mở ra, cung cấp tên mong muốn trong Tên bước đồng ruộng. Tiếp theo, chọn Tập lệnh Transact-SQL (T-SQL) trong Loại thả cái hộp xuống. Sau đó, chọn DBATools trong Cơ sở dữ liệu hộp thả xuống và viết truy vấn sau vào hộp văn bản lệnh:

EXEC Statistics_maintenance

Để định cấu hình lịch trình của công việc, hãy nhấp vào Lịch biểu tùy chọn trình đơn trong Công việc mới hộp thoại. Lịch trình công việc mới hộp thoại mở ra. Trong Tên , cung cấp tên lịch trình mong muốn. Trong ví dụ của chúng tôi, chúng tôi muốn công việc này được thực hiện hàng đêm lúc 1 giờ sáng, do đó trong mục Xảy ra hộp thả xuống trong Tần suất , chọn Hàng ngày . Trong phần Xảy ra một lần lúc trong trường Tần suất hàng ngày , nhập 01:00:00. Nhấp vào OK để đóng Lịch trình công việc mới và sau đó nhấp vào OK một lần nữa trong Công việc mới hộp thoại để đóng nó. Bây giờ chúng ta hãy thử nghiệm công việc này. Trong tác nhân SQL Server, nhấp chuột phải vào Update_St Statistics_Daily . Trong trường hợp công việc đã được thực hiện thành công, bạn sẽ thấy cửa sổ sau.

Tóm tắt

Trong bài viết này, các vấn đề sau đây đã được đề cập đến:1. Cách cập nhật số liệu thống kê của bảng bằng T-SQL Script. 2. Làm thế nào để có được thông tin về những thay đổi trong khối lượng dữ liệu và tần suất thay đổi dữ liệu. 3. Cách tạo tập lệnh cập nhật số liệu thống kê trên các bảng đang hoạt động. 4. Cách tạo SQL Server Agent Job để thực thi tập lệnh vào thời gian đã lên lịch.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kiểm tra xem bảng có tồn tại trong SQL Server không

  2. Cách tìm ngôn ngữ mặc định của người dùng trong SQL Server (T-SQL)

  3. Chèn hàng loạt tệp dữ liệu vào máy chủ SQL

  4. Triển khai SQL Server AlwaysOn Av available Groups trên Linux

  5. Tối ưu hóa truy vấn SQL - Cách xác định khi nào và nếu cần