Saya bekerja dengan SQL Server dan Oracle. Mungkin ada beberapa pengecualian, tetapi untuk platform tersebut jawaban umumnya adalah bahwa data dan indeks akan diperbarui pada saat yang sama.
Saya pikir akan sangat membantu untuk menarik perbedaan antara ketika indeks diperbarui untuk sesi yang memiliki transaksi dan untuk sesi lainnya. Secara default, sesi lain tidak akan melihat indeks yang diperbarui sampai transaksi dilakukan. Namun, sesi yang memiliki transaksi akan segera melihat indeks yang diperbarui.
Untuk satu cara untuk memikirkannya, pertimbangkan di meja dengan kunci utama. Dalam SQL Server dan Oracle ini diimplementasikan sebagai indeks. Sebagian besar waktu kami ingin ada kesalahan segera jika INSERT
dilakukan yang akan melanggar kunci utama. Agar itu terjadi, indeks harus diperbarui bersamaan dengan data. Perhatikan bahwa platform lain, seperti Postgres, memungkinkan batasan yang ditangguhkan yang diperiksa hanya ketika transaksi dilakukan.
Berikut ini adalah demo Oracle cepat yang menunjukkan kasus umum:
CREATE TABLE X_TABLE (PK INT NULL, PRIMARY KEY (PK));
INSERT INTO X_TABLE VALUES (1);
INSERT INTO X_TABLE VALUES (1); -- no commit
INSERT
Pernyataan kedua melempar kesalahan:
Kesalahan SQL: ORA-00001: kendala unik (XXXXXX.SYS_C00384850) dilanggar
00001.
00000 - "batasan unik (% s.% S) dilanggar"
* Penyebab: Pernyataan UPDATE atau INSERT berusaha memasukkan kunci duplikat. Untuk Oracle Tepercaya yang dikonfigurasi dalam mode MAC DBMS, Anda dapat melihat pesan ini jika entri duplikat ada di tingkat yang berbeda.
* Tindakan: Hapus batasan unik atau jangan masukkan kunci.
Jika Anda lebih suka melihat tindakan pembaruan indeks di bawah ini adalah demo sederhana di SQL Server. Pertama-tama buat tabel dua kolom dengan satu juta baris dan indeks nonclustered pada VAL
kolom:
DROP TABLE IF EXISTS X_TABLE_IX;
CREATE TABLE X_TABLE_IX (
ID INT NOT NULL,
VAL VARCHAR(10) NOT NULL
PRIMARY KEY (ID)
);
CREATE INDEX X_INDEX ON X_TABLE_IX (VAL);
-- insert one million rows with N from 1 to 1000000
INSERT INTO X_TABLE_IX
SELECT N, N FROM dbo.Getnums(1000000);
Kueri berikut dapat menggunakan indeks yang tidak tercakup karena indeks adalah indeks yang mencakup untuk permintaan itu. Ini berisi semua data yang diperlukan untuk menjalankannya. Seperti yang diharapkan, tidak ada pengembalian yang dikembalikan.
SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';
Sekarang mari kita mulai transaksi dan perbarui VAL
untuk hampir semua baris dalam tabel:
BEGIN TRANSACTION
UPDATE X_TABLE_IX
SET VAL = 'A'
WHERE ID <> 1;
Ini adalah bagian dari rencana permintaan untuk itu:
Dilingkari dengan warna merah adalah pembaruan ke indeks yang tidak tercakup. Dilingkari dengan warna biru adalah pembaruan ke indeks berkerumun, yang pada dasarnya adalah data tabel. Meskipun transaksi belum dilakukan, kami melihat bahwa data dan indeks diperbarui sebagai bagian dari eksekusi permintaan. Perhatikan bahwa Anda tidak akan selalu melihat ini dalam paket tergantung pada ukuran data yang terlibat bersama dengan faktor-faktor lainnya.
Dengan transaksi yang masih belum dilakukan, mari kembali ke SELECT
kueri dari atas.
SELECT *
FROM X_TABLE_IX
WHERE VAL = 'A';
Pengoptimal kueri masih dapat menggunakan indeks dan kali ini memperkirakan bahwa 999999 baris akan dikembalikan. Mengeksekusi kueri mengembalikan hasil yang diharapkan.
Itu adalah demo sederhana tetapi mudah-mudahan itu sedikit beres.
Selain itu, saya mengetahui beberapa kasus di mana dapat dikatakan bahwa indeks tidak segera diperbarui. Ini dilakukan karena alasan kinerja dan pengguna akhir tidak boleh dapat melihat data yang tidak konsisten. Misalnya, kadang-kadang menghapus tidak akan sepenuhnya diterapkan ke indeks di SQL Server. Proses latar belakang berjalan dan akhirnya membersihkan data. Anda dapat membaca tentang catatan hantu jika Anda penasaran.
Pengalaman saya adalah bahwa penyisipan 1.000.000 baris sebenarnya akan membutuhkan lebih banyak sumber daya dan membutuhkan waktu lebih lama untuk diselesaikan daripada jika Anda menggunakan sisipan batch. Ini dapat diimplementasikan, sebagai contoh, ke dalam 100 sisipan 10.000 baris.
Ini mengurangi overhead batch yang dimasukkan dan, jika batch gagal, itu adalah rollback yang lebih kecil.
Dalam kasus apa pun, untuk SQL Server ada utilitas bcp atau perintah BULK INSERT yang dapat digunakan untuk melakukan batch insert.
Dan, tentu saja, Anda juga dapat menerapkan kode Anda sendiri untuk menangani pendekatan ini.
sumber