Penulis Tamu :Derik Hammer (@SQLHammer)
Baru-baru ini Aaron Bertrand membuat blog tentang Mitos Kinerja SQL Server yang Berbahaya dan Menyebar. Sebagai perpanjangan dari seri blog ini, saya akan menyangkal mitos umum ini:
Membaca manual
Langsung ke sumbernya, saya melihat artikel Buku Online tentang tabel yang menyertakan variabel tabel. Meskipun artikel tersebut merujuk manfaat menggunakan variabel tabel, fakta bahwa variabel tersebut 100% dalam memori tidak terlihat jelas.
Namun, afirmasi yang hilang tidak berarti negatif. Sejak tabel OLTP Dalam Memori dirilis, sekarang ada lebih banyak dokumentasi di BOL untuk pemrosesan dalam memori. Di situlah saya menemukan artikel tentang membuat tabel temp dan variabel tabel lebih cepat dengan menggunakan pengoptimalan memori.
Seluruh artikel berkisar tentang bagaimana membuat objek sementara Anda menggunakan fitur OLTP dalam memori, dan di sinilah saya menemukan penegasan yang saya cari.
"Variabel tabel tradisional mewakili tabel dalam database tempdb. Untuk kinerja yang jauh lebih cepat, Anda dapat mengoptimalkan memori variabel tabel Anda."Variabel tabel bukan konstruksi dalam memori. Untuk menggunakan teknologi dalam memori, Anda harus secara eksplisit mendefinisikan TYPE yang memorinya dioptimalkan dan menggunakan TYPE tersebut untuk mendefinisikan variabel tabel Anda.
Buktikan
Dokumentasi adalah satu hal tetapi melihatnya dengan mata kepala sendiri adalah hal lain. Saya tahu bahwa tabel sementara membuat objek di tempdb dan akan menulis data ke disk. Pertama saya akan menunjukkan kepada Anda seperti apa tabel sementara dan kemudian saya akan menggunakan metode yang sama untuk memvalidasi hipotesis bahwa variabel tabel bertindak dengan cara yang sama.
Analisis catatan log
Kueri ini akan menjalankan CHECKPOINT untuk memberi saya titik awal yang bersih dan kemudian menunjukkan jumlah catatan log dan nama transaksi yang ada di log.
USE tempdb; GO CHECKPOINT; GO SELECT COUNT(*) [Count] FROM sys.fn_dblog (NULL, NULL); SELECT [Transaction Name] FROM sys.fn_dblog (NULL, NULL) WHERE [Transaction Name] IS NOT NULL;
Menjalankan T-SQL berulang kali menghasilkan tiga jumlah catatan yang konsisten di SQL Server 2016 SP1.
Ini membuat tabel sementara dan menampilkan rekaman objek, membuktikan bahwa ini adalah objek nyata di tempdb.
USE tempdb; GO DROP TABLE IF EXISTS #tmp; GO CREATE TABLE #tmp (id int NULL); SELECT name FROM sys.objects o WHERE is_ms_shipped = 0;
Sekarang saya akan menunjukkan catatan log lagi. Saya tidak akan menjalankan kembali perintah CHECKPOINT.
Dua puluh satu catatan log telah ditulis, membuktikan bahwa ini adalah penulisan pada disk, dan CREATE TABLE kami dengan jelas disertakan dalam catatan log ini.
Untuk membandingkan hasil ini dengan variabel tabel, saya akan mengatur ulang percobaan dengan menjalankan CHECKPOINT dan kemudian menjalankan T-SQL di bawah ini, membuat variabel tabel.
USE tempdb; GO DECLARE @var TABLE (id int NULL); SELECT name FROM sys.objects o WHERE is_ms_shipped = 0;
Sekali lagi kami memiliki catatan objek baru. Namun kali ini, namanya lebih acak daripada tabel sementara.
Ada delapan puluh dua catatan log baru dan nama transaksi yang membuktikan bahwa variabel saya sedang ditulis ke log, dan karena itu, ke disk.
Sebenarnya dalam memori
Sekarang saatnya saya membuat catatan log menghilang.
Saya membuat grup file OLTP dalam memori dan kemudian membuat tipe tabel yang dioptimalkan memori.
USE Test; GO CREATE TYPE dbo.inMemoryTableType AS TABLE ( id INT NULL INDEX ix1 ) WITH (MEMORY_OPTIMIZED = ON); GO
Saya mengeksekusi CHECKPOINT lagi dan kemudian membuat tabel memori yang dioptimalkan.
USE Test; GO DECLARE @var dbo.inMemoryTableType; INSERT INTO @var (id) VALUES (1) SELECT * from @var; GO
Setelah meninjau log, saya tidak melihat aktivitas log apa pun. Metode ini sebenarnya 100% dalam memori.
Bawa pulang
Variabel tabel menggunakan tempdb mirip dengan bagaimana tabel sementara menggunakan tempdb. Variabel tabel bukanlah konstruksi dalam memori tetapi dapat menjadi variabel tersebut jika Anda menggunakan tipe tabel yang ditentukan pengguna yang dioptimalkan memori. Seringkali saya menemukan tabel sementara menjadi pilihan yang jauh lebih baik daripada variabel tabel. Alasan utama untuk ini adalah karena variabel tabel tidak memiliki statistik dan, tergantung pada versi dan pengaturan SQL Server, perkiraan baris bekerja menjadi 1 baris atau 100 baris. Dalam kedua kasus ini, ini adalah tebakan dan menjadi bagian informasi yang salah dalam proses pengoptimalan kueri Anda.
Perhatikan bahwa beberapa perbedaan fitur ini dapat berubah seiring waktu – misalnya, dalam versi terbaru SQL Server, Anda dapat membuat indeks tambahan pada variabel tabel menggunakan sintaks indeks sebaris. Tabel berikut memiliki tiga indeks; kunci utama (ter-cluster secara default), dan dua indeks non-cluster:
DECLARE @t TABLE ( a int PRIMARY KEY, b int, INDEX x (b, a DESC), INDEX y (b DESC, a) );
Ada jawaban yang bagus di DBA Stack Exchange di mana Martin Smith secara mendalam merinci perbedaan antara variabel tabel dan tabel #temp:
- Apa perbedaan antara tabel sementara dan variabel tabel di SQL Server?