Pembaruan indeks unik dan penghitung modifikasi baris statistik


14

Diberikan tabel berikut, indeks berkerumun unik, dan statistik:

CREATE TABLE dbo.Banana
(
    pk integer NOT NULL, 
    c1 char(1) NOT NULL, 
    c2 char(1) NOT NULL
);

CREATE UNIQUE CLUSTERED INDEX pk ON dbo.Banana (pk);

CREATE STATISTICS c1 ON dbo.Banana (c1);
CREATE STATISTICS c2 ON dbo.Banana (c2);

INSERT dbo.Banana 
    (pk, c1, c2) 
VALUES 
    (1, 'A', 'W'), 
    (2, 'B', 'X'), 
    (3, 'C', 'Y'), 
    (4, 'D', 'Z');

-- Populate statistics
UPDATE STATISTICS dbo.Banana;

Contoh data

Penghitung modifikasi baris statistik jelas menunjukkan nol sebelum ada pembaruan:

-- Show statistics modification counters
SELECT
    stats_name = S.[name], 
    DDSP.stats_id,
    DDSP.[rows],
    DDSP.modification_counter
FROM sys.stats AS S
CROSS APPLY sys.dm_db_stats_properties(S.object_id, S.stats_id) AS DDSP
WHERE
    S.[object_id] = OBJECT_ID(N'dbo.Banana', N'U');

Penghitung modifikasi nol

Menambahkan setiap pknilai kolom dengan satu untuk setiap baris:

-- Increment pk in every row
UPDATE dbo.Banana 
SET pk += 1;

Menggunakan rencana eksekusi:

Split Sort Collapse rencana eksekusi

Ini menghasilkan penghitung modifikasi statistik berikut:

Penghitung modifikasi pasca-pembaruan

Pertanyaan

  1. Apa yang dilakukan operator Split, Sort, dan Collapse?
  2. Mengapa pkstatistik menunjukkan 2 modifikasi, tetapi c1dan c2menunjukkan 5?

Jawaban:


15

SQL Server selalu menggunakan kombinasi Split, Sort, dan Collapse operator ketika mempertahankan indeks unik sebagai bagian dari pembaruan yang mempengaruhi (atau mungkin mempengaruhi) lebih dari satu baris.

Bekerja melalui contoh dalam pertanyaan, kita bisa menulis pembaruan sebagai pembaruan satu baris terpisah untuk masing-masing dari empat baris yang ada:

-- Per row updates
UPDATE dbo.Banana SET pk = 2 WHERE pk = 1;
UPDATE dbo.Banana SET pk = 3 WHERE pk = 2;
UPDATE dbo.Banana SET pk = 4 WHERE pk = 3;
UPDATE dbo.Banana SET pk = 5 WHERE pk = 4;

Masalahnya adalah bahwa pernyataan pertama akan gagal, karena berubah pkdari 1 menjadi 2, dan sudah ada baris di mana pk= 2. Mesin penyimpanan SQL Server mengharuskan indeks unik tetap unik di setiap tahap pemrosesan, bahkan dalam satu pernyataan tunggal . Ini adalah masalah yang diselesaikan oleh Split, Sort, dan Collapse.

Membagi Membagi

Langkah pertama adalah Membagi setiap pernyataan pembaruan menjadi penghapusan diikuti oleh sisipan:

DELETE dbo.Banana WHERE pk = 1;
INSERT dbo.Banana (pk, c1, c2) VALUES (2, 'A', 'W');

DELETE dbo.Banana WHERE pk = 2;
INSERT dbo.Banana (pk, c1, c2) VALUES (3, 'B', 'X');

DELETE dbo.Banana WHERE pk = 3;
INSERT dbo.Banana (pk, c1, c2) VALUES (4, 'C', 'Y');

DELETE dbo.Banana WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');

Operator Split menambahkan kolom kode tindakan ke aliran (di sini diberi label Act1007):

Membagi properti

Kode tindakan adalah 1 untuk pembaruan, 3 untuk penghapusan, dan 4 untuk sisipan.

Menyortir Menyortir

Pernyataan terbagi di atas masih akan menghasilkan pelanggaran kunci unik sementara sementara, jadi langkah selanjutnya adalah mengurutkan pernyataan dengan kunci indeks unik yang diperbarui ( pkdalam kasus ini), lalu dengan kode tindakan. Untuk contoh ini, ini berarti bahwa penghapusan (3) pada kunci yang sama dipesan sebelum dimasukkan (4). Pesanan yang dihasilkan adalah:

-- Sort (pk, action)
DELETE dbo.Banana WHERE pk = 1;
DELETE dbo.Banana WHERE pk = 2;
INSERT dbo.Banana (pk, c1, c2) VALUES (2, 'A', 'W');
DELETE dbo.Banana WHERE pk = 3;
INSERT dbo.Banana (pk, c1, c2) VALUES (3, 'B', 'X');
DELETE dbo.Banana WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (4, 'C', 'Y');
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');

Sortir properti

Jatuh Jatuh

Tahap sebelumnya sudah cukup untuk menjamin terhindar dari pelanggaran keunikan palsu dalam semua kasus. Sebagai pengoptimalan, Collapse menggabungkan penghapusan dan sisipan yang berdekatan pada nilai kunci yang sama ke dalam pembaruan:

-- Collapse (pk)
DELETE dbo.Banana WHERE pk = 1;
UPDATE dbo.Banana SET c1 = 'A', c2 = 'W' WHERE pk = 2;
UPDATE dbo.Banana SET c1 = 'B', c2 = 'X' WHERE pk = 3;
UPDATE dbo.Banana SET c1 = 'C', c2 = 'Y' WHERE pk = 4;
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');

Pasangan hapus / sisipkan untuk pknilai 2, 3, dan 4 telah digabungkan ke dalam pembaruan, meninggalkan satu penghapusan tunggal pada pk= 1, dan sebuah sisipan untuk pk= 5.

Perkecil grup operator baris menurut kolom kunci, dan perbarui kode tindakan untuk mencerminkan hasil kehancuran:

Ciutkan properti

Pembaruan Indeks Clustered Pembaruan indeks berkerumun

Operator ini dilabeli sebagai Pembaruan, tetapi mampu menyisipkan, memperbarui, dan menghapus. Tindakan mana yang diambil oleh Pembaruan Indeks Clustered per baris ditentukan oleh nilai kode tindakan di baris itu. Operator memiliki properti Tindakan untuk mencerminkan mode operasi ini:

Properti tindakan Pembaruan Indeks Clustered


Penghitung modifikasi baris

Perhatikan bahwa ketiga pembaruan di atas tidak mengubah kunci indeks unik yang dipertahankan. Akibatnya, kami telah mengubah pembaruan ke kolom kunci dalam indeks menjadi pembaruan dari kolom non-kunci ( c1dan c2), ditambah dengan penghapusan dan sisipan. Baik penghapusan maupun penyisipan dapat menyebabkan pelanggaran kunci unik yang salah.

Sisipan atau penghapusan memengaruhi setiap kolom di baris, sehingga statistik yang terkait dengan setiap kolom akan menambah penghitung modifikasinya. Untuk pembaruan, hanya statistik dengan salah satu kolom yang diperbarui sebagai kolom utama yang penghitung modifikasinya bertambah (bahkan jika nilainya tidak berubah).

Penghitung modifikasi baris statistik karenanya menunjukkan 2 perubahan ke pk, dan 5 untuk c1dan c2:

-- Collapse (pk)
DELETE dbo.Banana WHERE pk = 1;                         -- All columns modified
UPDATE dbo.Banana SET c1 = 'A', c2 = 'W' WHERE pk = 2;  -- c1 and c2 modified
UPDATE dbo.Banana SET c1 = 'B', c2 = 'X' WHERE pk = 3;  -- c1 and c2 modified
UPDATE dbo.Banana SET c1 = 'C', c2 = 'Y' WHERE pk = 4;  -- c1 and c2 modified
INSERT dbo.Banana (pk, c1, c2) VALUES (5, 'D', 'Z');    -- All columns modified

Catatan: Hanya perubahan yang diterapkan pada objek dasar (heap atau clustered index) yang memengaruhi penghitung modifikasi baris statistik. Non-clustered indexes adalah struktur sekunder, yang mencerminkan perubahan yang telah dibuat pada objek dasar. Mereka tidak mempengaruhi penghitung modifikasi baris statistik sama sekali.

Jika suatu objek memiliki beberapa indeks unik, kombinasi Split, Sortir, Perkecil digunakan untuk mengatur pembaruan masing-masing. SQL Server mengoptimalkan kasus ini untuk indeks nonclustered dengan menyimpan hasil Split ke Spool Eager Table, kemudian memutar ulang yang ditetapkan untuk setiap indeks unik (yang akan memiliki Urutkan sendiri berdasarkan kunci indeks + kode tindakan, dan Perkecil).

Efek pada pembaruan statistik

Pembaruan statistik otomatis (jika diaktifkan) terjadi ketika pengoptimal permintaan membutuhkan informasi statistik dan pemberitahuan bahwa statistik yang ada sudah ketinggalan zaman (atau tidak valid karena perubahan skema). Statistik dianggap ketinggalan zaman ketika jumlah modifikasi yang dicatat melebihi ambang batas.

Pengaturan Split / Sort / Collapse menghasilkan modifikasi baris yang berbeda dicatat daripada yang diharapkan. Ini, pada gilirannya, berarti bahwa pembaruan statistik dapat dipicu cepat atau lambat daripada yang terjadi sebaliknya.

Pada contoh di atas, modifikasi baris untuk kolom kunci bertambah 2 (perubahan bersih) daripada 4 (satu untuk setiap baris tabel yang terpengaruh), atau 5 (satu untuk setiap penghapusan / perbarui / masukkan yang dihasilkan oleh Perkecil).

Selain itu, kolom non-kunci yang secara logis tidak diubah oleh kueri asli mengakumulasi modifikasi baris, yang dapat berjumlah sebanyak dua kali lipat baris tabel yang diperbarui (satu untuk setiap penghapusan, dan satu untuk setiap sisipan).


Jumlah perubahan yang direkam tergantung pada tingkat tumpang tindih antara nilai kolom kunci lama dan baru (dan sejauh mana penghapusan dan sisipan terpisah dapat diciutkan). Menyetel ulang tabel di antara setiap eksekusi, kueri berikut menunjukkan efek pada penghitung modifikasi baris dengan tumpang tindih yang berbeda:

UPDATE dbo.Banana SET pk = pk + 0; -- Full overlap

pk = pk + 0

UPDATE dbo.Banana SET pk = pk + 1;

pk = pk + 1

UPDATE dbo.Banana SET pk = pk + 2;

pk = pk + 2

UPDATE dbo.Banana SET pk = pk + 3;

pk = pk + 3

UPDATE dbo.Banana SET pk = pk + 4; -- No overlap

pk = pk + 4

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.