Jawaban:
Anda dapat mengingat hal-hal berikut ketika peduli tentang memperbarui statistik (disalin dari Rebuilding Indexes vs. Memperbarui Statistik (Benjamin Nevarez)
Secara default, UPDATE STATISTICS
pernyataan hanya menggunakan sampel rekaman dari tabel. Menggunakan UPDATE STATISTICS WITH FULLSCAN
akan memindai seluruh tabel.
Secara default, UPDATE STATISTICS
pernyataan memperbarui statistik indeks dan kolom. Menggunakan COLUMNS
opsi akan memperbarui statistik kolom saja. Menggunakan INDEX
opsi hanya akan memperbarui statistik indeks.
Membangun kembali indeks , misalnya dengan menggunakan ALTER INDEX … REBUILD
juga akan memperbarui statistik indeks dengan setara dengan menggunakan WITH FULLSCAN
kecuali jika tabel dipartisi, dalam hal ini statistik hanya sampel (berlaku untuk SQL Server 2012 dan yang lebih baru).
Statistik yang dibuat secara manual menggunakan CREATE STATISTICS
tidak diperbarui oleh ALTER INDEX ... REBUILD
operasi apa pun , termasuk ALTER TABLE ... REBUILD
. ALTER TABLE ... REBUILD
tidak memperbarui statistik untuk indeks berkerumun, jika ada yang didefinisikan pada tabel yang sedang dibangun kembali.
Mengatur ulang indeks , misalnya menggunakan ALTER INDEX … REORGANIZE
tidak memperbarui statistik apa pun.
Jawaban singkatnya adalah bahwa Anda perlu menggunakan UPDATE STATISTICS
untuk memperbarui statistik kolom dan bahwa pembangunan kembali indeks hanya akan memperbarui statistik indeks. Anda dapat memaksa pembaruan ke semua statistik di atas meja, termasuk statistik-indeks dan statistik yang dibuat secara manual, dengan UPDATE STATISTICS (tablename) WITH FULLSCAN;
sintaksis.
Kode berikut menggambarkan aturan yang diuraikan di atas:
Pertama, kita akan membuat tabel dengan beberapa kolom, dan indeks berkerumun:
USE tempdb;
IF OBJECT_ID(N'dbo.SomeTable', N'U') IS NOT NULL
DROP TABLE dbo.SomeTable;
CREATE TABLE dbo.SomeTable
(
rn int NOT NULL IDENTITY(1,1)
CONSTRAINT pk
PRIMARY KEY NONCLUSTERED
, i int NOT NULL INDEX i
, d sysname NOT NULL
) ON [PRIMARY] WITH (DATA_COMPRESSION = NONE);
CREATE UNIQUE CLUSTERED INDEX cx ON dbo.SomeTable (i, d);
CREATE STATISTICS d ON dbo.SomeTable (d) WITH FULLSCAN;
INSERT INTO dbo.SomeTable (d, i)
SELECT c1.name, c1.id
FROM sys.syscolumns c1;
Kueri ini menunjukkan tanggal ketika setiap objek statistik terakhir diperbarui:
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
Hasilnya menunjukkan belum ada pembaruan yang terjadi, yang benar karena kami baru saja membuat tabel:
╔═══════════════╦═══════════╦═══════════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═══════════╣ ║ dbo.SomeTable ║ cx ║ NULL ║ ║ dbo.SomeTable ║ i ║ NULL ║ ║ dbo.SomeTable ║ pk ║ NULL ║ ║ dbo.SomeTable ║ d ║ NULL ║ ╚═══════════════╩═══════════╩═══════════╝
Mari kita membangun kembali seluruh tabel, dan melihat apakah itu memperbarui statistik:
ALTER TABLE dbo.SomeTable REBUILD;
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ ║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║ ║ dbo.SomeTable ║ i ║ NULL ║ ║ dbo.SomeTable ║ pk ║ NULL ║ ║ dbo.SomeTable ║ d ║ NULL ║ ╚═══════════════╩═══════════╩═════════════════════ ════╝
Hasilnya menunjukkan hanya statistik indeks yang dikelompokkan yang diperbarui.
Selanjutnya, kami melakukan UPDATE STATS
operasi diskrit :
UPDATE STATISTICS dbo.SomeTable(d) WITH FULLSCAN;
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
Seperti yang Anda lihat, kami baru saja memperbarui statistik pada d
kolom:
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ ║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.590 ║ ║ dbo.SomeTable ║ i ║ NULL ║ ║ dbo.SomeTable ║ pk ║ NULL ║ ║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.597 ║ ╚═══════════════╩═══════════╩═════════════════════ ════╝
Sekarang, kami akan memperbarui statistik di seluruh tabel:
UPDATE STATISTICS dbo.SomeTable WITH FULLSCAN;
SELECT ObjectName = sc.name + N'.' + o.name
, StatsName = s.name
, StatsDate = STATS_DATE(s.object_id, s.stats_id)
FROM sys.stats s
INNER JOIN sys.objects o ON s.object_id = o.object_id
INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id
WHERE sc.name = N'dbo'
AND o.name = N'SomeTable';
╔═══════════════╦═══════════╦═════════════════════ ════╗ ║ ObjectName ║ StatsName ║ StatsDate ║ ╠═══════════════╬═══════════╬═════════════════════ ════╣ ║ dbo.SomeTable ║ cx ║ 2018-09-17 14: 09: 13.600 ║ ║ dbo.SomeTable ║ i ║ 2018-09-17 14: 09: 13.600 ║ ║ dbo.SomeTable ║ pk ║ 2018-09-17 14: 09: 13.603 ║ ║ dbo.SomeTable ║ d ║ 2018-09-17 14: 09: 13.607 ║ ╚═══════════════╩═══════════╩═════════════════════ ════╝
Seperti yang Anda lihat, satu-satunya cara untuk memastikan semua statistik diperbarui adalah dengan memperbarui masing-masing secara manual, atau memperbarui seluruh tabel dengan UPDATE STATISTICS (table);
.
ALTER INDEX ... REBUILD
atau UPDATE STATISTICS
pernyataan. Jika tabel itu sendiri dibangun kembali, hanya statistik indeks berkerumun diperbarui. FYI, kunci utama dan indeks berkerumun tidak selalu didukung oleh objek indeks yang sama.
Halaman Microsoft Documents untuk statistik SQL Server menyatakan :
Operasi seperti membangun kembali, defragmenting, atau mengatur ulang indeks tidak mengubah distribusi data. Oleh karena itu, Anda tidak perlu memperbarui statistik setelah menjalankan ALTER INDEX REBUILD, DBCC DBREINDEX, DBCC INDEXDEFRAG, atau operasi ALTER INDEX REORGANIZE . Query Optimizer memperbarui statistik ketika Anda membangun kembali indeks di atas meja atau tampilan dengan ALTER INDEX REBUILD atau DBCC DBREINDEX, namun pembaruan statistik ini adalah produk sampingan dari pembuatan kembali indeks. Query Optimizer tidak memperbarui statistik setelah operasi DBCC INDEXDEFRAG atau ALTER INDEX REORGANIZE.
REINDEX
statistik kolom yang diperbarui sebagai efek samping dari membangun kembali indeks - Anda tidak perlu memperbarui statistik. Data dalam tabel tidak berubah. Ini adalah data yang sama, hanya a) memindahkan lokasinya pada pelat pemintalan (ketika halaman direorganisasi), atau b) duduk di halaman yang berbeda (dalam kasus pembangunan kembali). Jadi: a re-indeks tidak update (beberapa) statistik: tidak ada kebutuhan untuk melakukannya.