Sqlserver
 sql >> Teknologi Basis Data >  >> RDS >> Sqlserver

Cara Memperbarui Statistik SQL Server untuk Tabel Besar

Dalam artikel saya sebelumnya, saya telah membahas secara singkat statistik basis data, pentingnya, dan mengapa statistik harus diperbarui. Selain itu, saya telah menunjukkan proses langkah demi langkah untuk membuat rencana pemeliharaan SQL Server untuk memperbarui statistik. Pada artikel ini akan dijelaskan masalah-masalah berikut:1. Cara mengupdate statistik menggunakan Perintah T-SQL. 2. Bagaimana mengidentifikasi tabel yang sering diupdate menggunakan T-SQL dan juga bagaimana mengupdate statistik tabel dengan data yang sering disisipkan/diperbarui/dihapus.

Memperbarui statistik menggunakan T-SQL

Anda dapat memperbarui statistik menggunakan skrip T-SQL. Jika Anda ingin memperbarui statistik menggunakan T-SQL atau SQL Server management studio, Anda memerlukan ALTER database izin pada database. Lihat contoh kode T-SQL untuk memperbarui statistik tabel tertentu:

UPDATE STATISTICS <schema_name>.<table_name>.

Mari kita perhatikan contoh memperbarui statistik OrderLines tabel WideWorldImporters basis data. Skrip berikut akan melakukannya.

UPDATE STATISTICS [Sales].[OrderLines]

Jika Anda ingin memperbarui statistik indeks tertentu, Anda dapat menggunakan skrip berikut:

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

Jika Anda ingin memperbarui statistik IX_Sales_OrderLines_Perf_20160301_02 indeks OrderLines tabel, Anda dapat menjalankan skrip berikut:

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

Anda juga dapat memperbarui statistik seluruh database. Jika Anda memiliki database yang sangat kecil dengan beberapa tabel dan jumlah data yang sedikit, maka Anda dapat memperbarui statistik semua tabel dalam database. Lihat skrip berikut:

USE wideworldimporters 
go 
EXEC Sp_updatestats

Memperbarui statistik untuk tabel dengan data yang sering dimasukkan / diperbarui / dihapus

Pada database besar, penjadwalan tugas statistik menjadi rumit, terutama bila Anda hanya memiliki beberapa jam untuk melakukan pemeliharaan indeks, memperbarui statistik, dan memenuhi tugas pemeliharaan lainnya. Yang saya maksud dengan database besar adalah database yang berisi ribuan tabel dan setiap tabel berisi ribuan baris. Misalnya, kami memiliki database bernama X. Ini memiliki ratusan tabel, dan setiap tabel memiliki jutaan baris. Dan hanya beberapa tabel yang sering diperbarui. Tabel lain jarang diubah dan sangat sedikit transaksi yang dilakukan pada tabel tersebut. Seperti yang saya sebutkan sebelumnya, untuk menjaga kinerja database tetap sesuai standar, statistik tabel harus diperbarui. Jadi kami membuat rencana pemeliharaan SQL untuk memperbarui statistik semua tabel dalam database X. Ketika SQL server memperbarui statistik tabel, itu menggunakan sejumlah besar sumber daya yang dapat menyebabkan masalah kinerja. Jadi, butuh waktu lama untuk memperbarui statistik dari ratusan tabel besar dan sementara statistik diperbarui, kinerja database berkurang secara signifikan. Dalam keadaan seperti itu, selalu disarankan untuk memperbarui statistik hanya untuk tabel yang sering diperbarui. Anda dapat melacak perubahan volume data atau jumlah baris dari waktu ke waktu dengan menggunakan tampilan pengelolaan dinamis berikut:1. sys.partitions memberikan informasi tentang jumlah baris dalam sebuah tabel. 2. sys.dm_db_partition_stats memberikan informasi tentang jumlah baris dan jumlah halaman, per partisi. 3. sys.dm_db_index_physical_stats memberikan informasi tentang jumlah baris dan halaman, ditambah informasi tentang fragmentasi indeks dan banyak lagi. Detail tentang volume data penting, tetapi tidak membuat gambaran aktivitas database menjadi lengkap. Misalnya, tabel staging yang memiliki jumlah record yang hampir sama dapat dihapus dari tabel atau disisipkan ke dalam tabel setiap hari. Karena itu, snapshot dari jumlah baris akan menunjukkan bahwa tabel itu statis. Ada kemungkinan bahwa catatan yang ditambahkan dan dihapus memiliki nilai yang sangat berbeda yang sangat mengubah distribusi data. Dalam hal ini, memperbarui statistik secara otomatis di SQL Server membuat statistik menjadi tidak berarti. Oleh karena itu, melacak jumlah modifikasi pada tabel sangat berguna. Ini dapat dilakukan dengan cara berikut:1. rowmodctr kolom di sys.sysindexes 2. modified_count kolom di sys.system_internals_partition_columns 3. modification_counter kolom di sys.dm_db_stats_properties Jadi, seperti yang saya jelaskan sebelumnya, jika Anda memiliki waktu terbatas untuk pemeliharaan database, selalu disarankan untuk memperbarui statistik hanya untuk tabel dengan frekuensi perubahan data yang lebih tinggi (masukkan / perbarui / hapus). Untuk melakukannya secara efisien, saya telah membuat skrip yang memperbarui statistik untuk tabel "aktif". Script melakukan tugas berikut:• Mendeklarasikan parameter yang diperlukan • Membuat tabel sementara bernama #tempstatistics untuk menyimpan nama tabel, nama skema, dan nama database • Membuat tabel lain bernama #tempdatabase untuk menyimpan nama database. Pertama, jalankan skrip berikut untuk membuat dua tabel:

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

Selanjutnya, tulis while loop untuk membuat kueri SQL dinamis yang mengulangi semua database dan menyisipkan daftar tabel yang memiliki penghitung modifikasi lebih besar dari 200 ke dalam #tempstatistics meja. Untuk mendapatkan informasi tentang perubahan data, saya menggunakan sys.dm_db_stats_properties . Pelajari contoh kode berikut:

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

Sekarang, buat loop kedua di dalam loop pertama. Ini akan menghasilkan Query SQL dinamis yang memperbarui statistik dengan pemindaian penuh. Lihat contoh kode di bawah ini:

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

Setelah eksekusi skrip selesai, semua tabel sementara akan dihapus.

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

Seluruh script akan muncul sebagai berikut:

--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

Anda juga dapat mengotomatiskan skrip ini dengan membuat pekerjaan Agen Server SQL yang akan mengeksekusinya pada waktu yang dijadwalkan. Petunjuk langkah demi langkah untuk mengotomatisasi pekerjaan ini diberikan di bawah ini.

Membuat Pekerjaan SQL

Pertama, mari buat SQL Job untuk mengotomatisasi proses. Untuk melakukannya, buka SSMS, sambungkan ke server yang diinginkan dan perluas SQL Server Agent, klik kanan pada Pekerjaan dan pilih Pekerjaan Baru . Di Pekerjaan Baru kotak dialog, ketik nama yang diinginkan di Nama bidang. Sekarang, klik Langkah opsi menu di panel kiri Pekerjaan Baru kotak dialog, lalu klik Baru dalam Langkah jendela. Dalam Langkah Pekerjaan Baru kotak dialog, yang terbuka, berikan nama yang diinginkan di Nama langkah bidang. Selanjutnya, pilih Skrip Transact-SQL (T-SQL) di Jenis kotak drop-down. Kemudian, pilih DBATools di Database kotak drop-down dan tulis kueri berikut di kotak teks perintah:

EXEC Statistics_maintenance

Untuk mengonfigurasi jadwal pekerjaan, klik Jadwal opsi menu di Pekerjaan Baru kotak dialog. Jadwal Kerja Baru kotak dialog terbuka. Di Nama bidang, berikan nama jadwal yang diinginkan. Dalam contoh kami, kami ingin pekerjaan ini dieksekusi setiap malam pada jam 1 pagi, oleh karena itu dalam Terjadi kotak tarik-turun di Frekuensi bagian, pilih Harian . Dalam Terjadi sekali pada bidang di Frekuensi harian bagian, masukkan 01:00:00. Klik Oke untuk menutup Jadwal Kerja Baru jendela lalu klik OK lagi di Pekerjaan Baru kotak dialog untuk menutupnya. Sekarang mari kita uji pekerjaan ini. Di bawah SQL Server Agent, klik kanan Update_Statistics_Daily . Jika pekerjaan telah berhasil dijalankan, Anda akan melihat jendela berikut.

Ringkasan

Dalam artikel ini, masalah berikut telah dibahas:1. Cara memperbarui statistik tabel menggunakan T-SQL Script. 2. Bagaimana memperoleh informasi tentang perubahan volume data dan frekuensi perubahan data. 3. Cara membuat skrip yang memperbarui statistik pada tabel yang aktif. 4. Cara membuat SQL Server Agent Job untuk mengeksekusi skrip pada waktu yang dijadwalkan.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL Server memblokir akses ke prosedur 'sys.sp_OACreate' dari komponen 'Ole Automation Procedures'

  2. Cara mengimpor file DBF di SQL Server

  3. Apa cara terbaik untuk memanfaatkan huruf pertama dari setiap kata dalam string di SQL Server?

  4. Bagaimana cara membatasi NULL sebagai parameter untuk prosedur tersimpan SQL Server?

  5. Buat Kolom "Terakhir Dimodifikasi" di SQL Server