Database
 sql >> Teknologi Basis Data >  >> RDS >> Database

Logging Minimal dengan INSERT…SELECT dan Fast Load Context

Pos ini memberikan informasi baru tentang prasyarat untuk beban massal yang dicatat minimal saat menggunakan INSERT...SELECT ke dalam tabel yang diindeks .

Fasilitas internal yang mengaktifkan kasus ini disebut FastLoadContext . Itu dapat diaktifkan dari SQL Server 2008 hingga 2014 inklusif menggunakan tanda pelacakan terdokumentasi 610. Dari SQL Server 2016 dan seterusnya, FastLoadContext diaktifkan secara default; tanda jejak tidak diperlukan.

Tanpa FastLoadContext , satu-satunya sisipan indeks yang dapat dilog minimal apakah itu menjadi kosong indeks berkerumun tanpa indeks sekunder, seperti yang tercakup dalam bagian dua dari seri ini. Log minimal kondisi untuk tabel heap yang tidak diindeks dibahas di bagian satu.

Untuk latar belakang selengkapnya, lihat Panduan Pemuatan Kinerja Data dan Tim Macan catatan tentang perubahan perilaku untuk SQL Server 2016.

Konteks Muat Cepat

Sebagai pengingat cepat, RowsetBulk fasilitas (tercakup dalam bagian 1 dan 2) memungkinkan dicatat secara minimal beban massal untuk:

  • Heap kosong dan tidak kosong tabel dengan:
    • Penguncian tabel; dan
    • Tidak ada indeks sekunder.
  • Tabel kluster kosong , dengan:
    • Penguncian tabel; dan
    • Tidak ada indeks sekunder; dan
    • DMLRequestSort=true pada Sisipkan Indeks Berkelompok operator.

FastLoadContext jalur kode menambahkan dukungan untuk dicatat secara minimal dan bersamaan beban massal pada:

  • Kosong dan tidak kosong berkelompok indeks b-tree.
  • Kosong dan tidak kosong nonclustered indeks b-tree dikelola oleh khusus Sisipkan Indeks operator paket.

FastLoadContext juga membutuhkan DMLRequestSort=true pada operator paket yang sesuai dalam semua kasus.

Anda mungkin telah melihat tumpang tindih antara RowsetBulk dan FastLoadContext untuk tabel berkerumun kosong tanpa indeks sekunder. Sebuah TABLOCK petunjuk tidak diperlukan dengan FastLoadContext , tetapi tidak wajib absen antara. Akibatnya, sisipan yang sesuai dengan TABLOCK mungkin masih memenuhi syarat untuk logging minimal melalui FastLoadContext jika gagal detail RowsetBulk tes.

FastLoadContext dapat dinonaktifkan di SQL Server 2016 menggunakan bendera pelacakan terdokumentasi 692. Saluran Debug Extended Event fastloadcontext_enabled dapat digunakan untuk memantau FastLoadContext penggunaan per partisi indeks (rowset). Acara ini tidak diaktifkan untuk RowsetBulk beban.

Pencatatan log campuran

Satu INSERT...SELECT pernyataan menggunakan FastLoadContext boleh masuk sepenuhnya beberapa baris saat minimal login lainnya.

Baris disisipkan satu per satu oleh Indeks Sisipan operator dan masuk sepenuhnya dalam kasus berikut:

  • Semua baris ditambahkan ke pertama halaman indeks, jika indeks kosong di awal operasi.
  • Baris ditambahkan ke yang sudah ada halaman indeks.
  • Baris dipindahkan antar halaman dengan pemisahan halaman.

Jika tidak, baris dari aliran penyisipan yang dipesan akan ditambahkan ke laman baru menggunakan yang dioptimalkan, dan dicatat secara minimal jalur kode. Setelah sebanyak mungkin baris ditulis ke halaman baru, baris tersebut langsung ditautkan ke dalam struktur indeks target yang ada.

Halaman yang baru ditambahkan belum tentu menjadi penuh (meskipun jelas itu adalah kasus yang ideal) karena SQL Server harus berhati-hati untuk tidak menambahkan baris ke halaman baru yang secara logis milik yang sudah ada halaman indeks. Halaman baru akan 'dijahit ke dalam' indeks sebagai satu unit, jadi kami tidak dapat memiliki baris apa pun di halaman baru yang termasuk di tempat lain. Ini terutama merupakan masalah saat menambahkan baris di dalam rentang kunci indeks yang ada, bukan sebelum memulai atau setelah akhir rentang kunci indeks yang ada.

Masih mungkin untuk menambahkan halaman baru di dalam rentang kunci indeks yang ada, tetapi baris baru harus diurutkan lebih tinggi dari kunci tertinggi pada sebelumnya halaman indeks yang ada dan urutkan lebih rendah dari kunci terendah pada berikut halaman indeks yang ada. Untuk peluang terbaik mencapai pencatatan log minimal dalam keadaan ini, pastikan baris yang disisipkan tidak tumpang tindih dengan baris yang ada sejauh mungkin.

DMLRequestSort Conditions

Ingat bahwa FastLoadContext hanya dapat diaktifkan jika DMLRequestSort disetel ke benar untuk Indeks Sisipan yang sesuai operator dalam rencana eksekusi.

Ada dua jalur kode utama yang dapat mengatur DMLRequestSort untuk benar untuk sisipan indeks. Jalur mana pun mengembalikan benar sudah cukup.

1. FOptimizeInsert

sqllang!CUpdUtil::FOptimizeInsert kode membutuhkan:

  • Lebih dari 250 baris perkiraan untuk dimasukkan; dan
  • Lebih dari 2 halaman perkiraan masukkan ukuran data; dan
  • Indeks target harus memiliki kurang dari 3 halaman lembar .

Kondisi ini sama dengan RowsetBulk pada indeks berkerumun kosong, dengan persyaratan tambahan untuk tidak lebih dari dua halaman tingkat daun indeks. Perhatikan baik-baik bahwa ini mengacu pada ukuran indeks yang ada sebelum disisipkan, tidak perkiraan ukuran data yang akan ditambahkan.

Script di bawah ini adalah modifikasi dari demo yang digunakan di bagian sebelumnya dalam seri ini. Ini menunjukkan logging minimal bila kurang dari tiga halaman indeks diisi sebelum tes INSERT...SELECT berjalan. Skema tabel pengujian sedemikian rupa sehingga 130 baris dapat dimuat pada satu halaman 8KB ketika versi baris dinonaktifkan untuk database. Pengganda di TOP pertama klausa dapat diubah untuk menentukan jumlah halaman indeks yang ada sebelum tes INSERT...SELECT dijalankan:

IF OBJECT_ID(N'dbo.Test', N'U') IS NOT NULL
BEGIN
    DROP TABLE dbo.Test;
END;
GO
CREATE TABLE dbo.Test 
(
    id integer NOT NULL IDENTITY
        CONSTRAINT [PK dbo.Test (id)]
        PRIMARY KEY,
    c1 integer NOT NULL,
    padding char(45) NOT NULL
        DEFAULT ''
);
GO
-- 130 rows per page for this table 
-- structure with row versioning off
INSERT dbo.Test
    (c1)
SELECT TOP (3 * 130)    -- Change the 3 here
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV;
GO
-- Show physical index statistics
-- to confirm the number of pages
SELECT
    DDIPS.index_type_desc,
    DDIPS.alloc_unit_type_desc,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(), 
    OBJECT_ID(N'dbo.Test', N'U'), 
    1,      -- Index ID
    NULL,   -- Partition ID
    'DETAILED'
) AS DDIPS
WHERE
    DDIPS.index_level = 0;  -- leaf level only
GO
-- Clear the plan cache
DBCC FREEPROCCACHE;
GO
-- Clear the log
CHECKPOINT;
GO
-- Main test
INSERT dbo.Test
    (c1)
SELECT TOP (269)
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV;
GO
-- Show log entries
SELECT
    FD.Operation,
    FD.Context,
    FD.[Log Record Length],
    FD.[Log Reserve],
    FD.AllocUnitName,
    FD.[Transaction Name],
    FD.[Lock Information],
    FD.[Description]
FROM sys.fn_dblog(NULL, NULL) AS FD;
GO
-- Count the number of  fully-logged rows
SELECT 
    [Fully Logged Rows] = COUNT_BIG(*) 
FROM sys.fn_dblog(NULL, NULL) AS FD
WHERE 
    FD.Operation = N'LOP_INSERT_ROWS'
    AND FD.Context = N'LCX_CLUSTERED'
    AND FD.AllocUnitName = N'dbo.Test.PK dbo.Test (id)';
GO

Saat indeks berkerumun dimuat sebelumnya dengan 3 halaman , sisipan pengujian sepenuhnya dicatat (catatan detail log transaksi dihilangkan untuk singkatnya):

Saat tabel dimuat sebelumnya dengan hanya 1 atau 2 halaman , sisipan pengujian dicatat minimal :

Saat tabel tidak dimuat sebelumnya dengan halaman mana pun, pengujian ini setara dengan menjalankan demo tabel berkerumun kosong dari bagian dua, tetapi tanpa TABLOCK petunjuk:

130 baris pertama sepenuhnya dicatat . Ini karena indeks kosong sebelum kita mulai, dan 130 baris muat di halaman pertama. Ingat, halaman pertama selalu dicatat sepenuhnya saat FastLoadContext digunakan dan indeks kosong sebelumnya. 139 baris yang tersisa disisipkan dengan pencatatan log minimal .

Jika TABLOCK petunjuk ditambahkan ke sisipan, semua halaman dicatat minimal (termasuk yang pertama) karena beban indeks berkerumun kosong sekarang memenuhi syarat untuk RowsetBulk mekanisme (dengan biaya mengambil Sch-M kunci).

2. FDemandRowsSortedForPerformance

Jika FOptimizeInsert tes gagal, DMLRequestSort mungkin masih disetel ke true dengan serangkaian tes kedua di sqllang!CUpdUtil::FDemandRowsSortedForPerformance kode. Kondisi ini sedikit lebih kompleks, jadi akan berguna untuk mendefinisikan beberapa parameter:

  • P – jumlah halaman tingkat daun yang ada di indeks target .
  • Iperkiraan jumlah baris yang akan disisipkan.
  • R =P / I (halaman target per baris yang disisipkan).
  • T – jumlah partisi target (1 untuk tidak dipartisi).

Logika untuk menentukan nilai DMLRequestSort maka:

  • Jika P <= 16 kembalikan salah , jika tidak :
    • Jika R < 8 :
      • Jika P > 524 kembalikan benar , jika tidak salah .
    • Jika R >= 8 :
      • Jika T > 1 dan I > 250 kembalikan benar , jika tidak salah .

Tes di atas dievaluasi oleh prosesor kueri selama kompilasi rencana. Ada kondisi akhir dievaluasi oleh kode mesin penyimpanan (IndexDataSetSession::WakeUpInternal ) pada waktu eksekusi:

  • DMLRequestSort saat ini benar; dan
  • I >= 100 .

Kami akan memecah semua logika ini menjadi bagian-bagian yang dapat dikelola selanjutnya.

Lebih dari 16 halaman target yang ada

Tes pertama P <= 16 berarti indeks dengan kurang dari 17 halaman daun yang ada tidak akan memenuhi syarat untuk FastLoadContext melalui jalur kode ini. Untuk memperjelas hal ini, P adalah jumlah halaman tingkat daun dalam indeks target sebelum INSERT...SELECT dijalankan.

Untuk mendemonstrasikan bagian logika ini, kami akan memuat terlebih dahulu tabel clustered pengujian dengan 16 halaman dari data. Ini memiliki dua efek penting (ingat kedua jalur kode harus mengembalikan false berakhir dengan salah nilai untuk DMLRequestSort ):

  1. Ini memastikan bahwa FOptimizeInsert sebelumnya uji gagal , karena syarat ketiga tidak terpenuhi (P < 3 ).
  2. P <= 16 kondisi di FDemandRowsSortedForPerformance juga akan tidak bertemu.

Oleh karena itu kami mengharapkan FastLoadContext untuk tidak diaktifkan. Skrip demo yang dimodifikasi adalah:

IF OBJECT_ID(N'dbo.Test', N'U') IS NOT NULL
BEGIN
    DROP TABLE dbo.Test;
END;
GO
CREATE TABLE dbo.Test 
(
    id integer NOT NULL IDENTITY
        CONSTRAINT [PK dbo.Test (id)]
        PRIMARY KEY,
    c1 integer NOT NULL,
    padding char(45) NOT NULL
        DEFAULT ''
);
GO
-- 130 rows per page for this table 
-- structure with row versioning off
INSERT dbo.Test
    (c1)
SELECT TOP (16 * 130) -- 16 pages
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV;
GO
-- Show physical index statistics
-- to confirm the number of pages
SELECT
    DDIPS.index_type_desc,
    DDIPS.alloc_unit_type_desc,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(), 
    OBJECT_ID(N'dbo.Test', N'U'), 
    1,      -- Index ID
    NULL,   -- Partition ID
    'DETAILED'
) AS DDIPS
WHERE
    DDIPS.index_level = 0;  -- leaf level only
GO
-- Clear the plan cache
DBCC FREEPROCCACHE;
GO
-- Clear the log
CHECKPOINT;
GO
-- Main test
INSERT dbo.Test
    (c1)
SELECT TOP (269)
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV1
CROSS JOIN master.dbo.spt_values AS SV2;
GO
-- Show log entries
SELECT
    FD.Operation,
    FD.Context,
    FD.[Log Record Length],
    FD.[Log Reserve],
    FD.AllocUnitName,
    FD.[Transaction Name],
    FD.[Lock Information],
    FD.[Description]
FROM sys.fn_dblog(NULL, NULL) AS FD;
GO
-- Count the number of  fully-logged rows
SELECT 
    [Fully Logged Rows] = COUNT_BIG(*) 
FROM sys.fn_dblog(NULL, NULL) AS FD
WHERE 
    FD.Operation = N'LOP_INSERT_ROWS'
    AND FD.Context = N'LCX_CLUSTERED'
    AND FD.AllocUnitName = N'dbo.Test.PK dbo.Test (id)';

Semua 269 baris sepenuhnya dicatat seperti yang diperkirakan:

Perhatikan bahwa tidak peduli seberapa tinggi kita menetapkan jumlah baris baru untuk disisipkan, skrip di atas tidak akan pernah menghasilkan penebangan minimal karena P <= 16 tes (dan P < 3 uji di FOptimizeInsert ).

Jika Anda memilih untuk menjalankan demo sendiri dengan jumlah baris yang lebih banyak, beri komentar di bagian yang menunjukkan catatan log transaksi individual, jika tidak, Anda akan menunggu sangat lama, dan SSMS mungkin macet. (Agar adil, itu mungkin dilakukan, tetapi mengapa menambah risiko.)

Rasio halaman per baris yang disisipkan

Jika ada 17 atau lebih halaman daun dalam indeks yang ada, sebelumnya P <= 16 tes tidak akan gagal. Bagian logika selanjutnya membahas rasio halaman yang ada ke baris yang baru dimasukkan . Ini juga harus lulus untuk mencapai pembuatan log minimal . Sebagai pengingat, kondisi yang relevan adalah:

  • Rasio R =P / I .
  • Jika R < 8 :
    • Jika P > 524 kembalikan benar , jika tidak salah .

Kita juga harus mengingat pengujian mesin penyimpanan terakhir untuk setidaknya 100 baris:

  • I >= 100 .

Mengatur ulang kondisi tersebut sedikit, semua berikut ini harus benar:

  1. P > 524 (halaman indeks yang ada)
  2. I >= 100 (perkiraan baris yang disisipkan)
  3. P / I < 8 (rasio R )

Ada beberapa cara untuk memenuhi ketiga kondisi tersebut secara bersamaan. Mari kita pilih nilai seminimal mungkin untuk P (525) dan I (100) memberikan R nilai (525/100) =5,25. Ini memenuhi (R < 8 test), jadi kami berharap kombinasi ini menghasilkan logging minimal :

IF OBJECT_ID(N'dbo.Test', N'U') IS NOT NULL
BEGIN
    DROP TABLE dbo.Test;
END;
GO
CREATE TABLE dbo.Test 
(
    id integer NOT NULL IDENTITY
        CONSTRAINT [PK dbo.Test (id)]
        PRIMARY KEY,
    c1 integer NOT NULL,
    padding char(45) NOT NULL
        DEFAULT ''
);
GO
-- 130 rows per page for this table 
-- structure with row versioning off
INSERT dbo.Test
    (c1)
SELECT TOP (525 * 130) -- 525 pages
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV1
CROSS JOIN master.dbo.spt_values AS SV2;
GO
-- Show physical index statistics
-- to confirm the number of pages
SELECT
    DDIPS.index_type_desc,
    DDIPS.alloc_unit_type_desc,
    DDIPS.page_count,
    DDIPS.record_count,
    DDIPS.avg_record_size_in_bytes
FROM sys.dm_db_index_physical_stats
(
    DB_ID(), 
    OBJECT_ID(N'dbo.Test', N'U'), 
    1,      -- Index ID
    NULL,   -- Partition ID
    'DETAILED'
) AS DDIPS
WHERE
    DDIPS.index_level = 0;  -- leaf level only
GO
-- Clear the plan cache
DBCC FREEPROCCACHE;
GO
-- Clear the log
CHECKPOINT;
GO
-- Main test
INSERT dbo.Test
    (c1)
SELECT TOP (100)
    CHECKSUM(NEWID())
FROM master.dbo.spt_values AS SV1
CROSS JOIN master.dbo.spt_values AS SV2;
GO
-- Show log entries
SELECT
    FD.Operation,
    FD.Context,
    FD.[Log Record Length],
    FD.[Log Reserve],
    FD.AllocUnitName,
    FD.[Transaction Name],
    FD.[Lock Information],
    FD.[Description]
FROM sys.fn_dblog(NULL, NULL) AS FD;
GO
-- Count the number of  fully-logged rows
SELECT 
    [Fully Logged Rows] = COUNT_BIG(*) 
FROM sys.fn_dblog(NULL, NULL) AS FD
WHERE 
    FD.Operation = N'LOP_INSERT_ROWS'
    AND FD.Context = N'LCX_CLUSTERED'
    AND FD.AllocUnitName = N'dbo.Test.PK dbo.Test (id)';

100 baris INSERT...SELECT memang minimal dicatat :

Mengurangi perkiraan memasukkan baris ke 99 (melanggar I >= 100 ), dan/atau mengurangi jumlah halaman indeks yang ada menjadi 524 (melanggar P > 524 ) menghasilkan pencatatan log penuh . Kami juga dapat membuat perubahan sedemikian rupa sehingga R tidak kurang dari 8 untuk menghasilkan penebangan penuh . Misalnya, menyetel P = 1000 dan I = 125 memberikan R = 8 , dengan hasil sebagai berikut:

125 baris yang disisipkan sepenuhnya dicatat seperti yang diharapkan. (Ini bukan karena halaman pertama masuk penuh, karena indeks tidak kosong sebelumnya.)

Rasio halaman untuk indeks yang dipartisi

Jika semua tes sebelumnya gagal, satu tes yang tersisa memerlukan R >= 8 dan dapat hanya puas ketika jumlah partisi (T ) lebih besar dari 1 dan ada lebih dari 250 perkiraan baris yang disisipkan (I ). Ingat:

  • Jika R >= 8 :
    • Jika T > 1 dan I > 250 kembalikan benar , jika tidak salah .

Satu kehalusan:Untuk dipartisi indeks, aturan yang mengatakan semua baris halaman pertama dicatat sepenuhnya (untuk indeks yang awalnya kosong) berlaku per partisi . Untuk objek dengan 15.000 partisi, itu berarti 15.000 halaman 'pertama' yang dicatat sepenuhnya.

Ringkasan dan Pemikiran Akhir

Rumus dan urutan evaluasi yang dijelaskan dalam isi didasarkan pada pemeriksaan kode menggunakan debugger. Mereka disajikan dalam bentuk yang secara dekat mewakili waktu dan urutan yang digunakan dalam kode sebenarnya.

Hal ini dimungkinkan untuk menyusun ulang dan menyederhanakan kondisi tersebut sedikit, untuk menghasilkan ringkasan yang lebih ringkas dari persyaratan praktis untuk logging minimal saat memasukkan ke dalam b-tree menggunakan INSERT...SELECT . Ekspresi halus di bawah ini menggunakan tiga parameter berikut:

  • P =jumlah yang ada indeks halaman tingkat daun.
  • I =perkiraan jumlah baris yang akan disisipkan.
  • S =perkiraan masukkan ukuran data di halaman 8KB.

Pemuatan massal Rowset

  • Menggunakan sqlmin!RowsetBulk .
  • Memerlukan kosong target indeks berkerumun dengan TABLOCK (atau setara).
  • Memerlukan DMLRequestSort = true pada Sisipkan Indeks Berkelompok operator.
  • DMLRequestSort disetel true jika I > 250 dan S > 2 .
  • Semua baris yang disisipkan dicatat minimal .
  • Sebuah Sch-M lock mencegah akses tabel secara bersamaan.

Konteks pemuatan cepat

  • Menggunakan sqlmin!FastLoadContext .
  • Mengaktifkan dicatat secara minimal menyisipkan ke indeks b-tree:
    • Berkelompok atau tidak berkerumun.
    • Dengan atau tanpa kunci meja.
    • Indeks target kosong atau tidak.
  • Memerlukan DMLRequestSort = true pada Indeks Sisipan associated yang terkait operator paket.
  • Hanya baris yang ditulis ke halaman baru brand dimuat secara massal dan dilog minimal .
  • Halaman pertama dari indeks kosong yang sebelumnya partisi selalu tercatat sepenuhnya .
  • Minimum mutlak I >= 100 .
  • Memerlukan tanda pelacakan 610 sebelum SQL Server 2016.
  • Tersedia secara default dari SQL Server 2016 (trace flag 692 dinonaktifkan).

DMLRequestSort disetel true untuk:

  • Indeks apa saja (dipartisi atau tidak) jika:
    • I > 250 dan P < 3 dan S > 2; atau
    • I >= 100 dan P > 524 dan P < I * 8

Untuk hanya indeks yang dipartisi (dengan> 1 partisi), DMLRequestSort juga disetel true jika:

  • I > 250 dan P > 16 dan P >= I * 8

Ada beberapa kasus menarik yang muncul dari FastLoadContext tersebut syarat:

  • Semua menyisipkan ke tidak dipartisi indeks dengan antara 3 dan 524 (termasuk) halaman daun yang ada akan dicatat sepenuhnya terlepas dari jumlah dan ukuran total baris yang ditambahkan. Ini akan sangat mempengaruhi sisipan besar ke tabel kecil (tetapi tidak kosong).
  • Semua menyisipkan ke dipartisi indeks dengan antara 3 dan 16 halaman yang ada akan sepenuhnya dicatat .
  • Sisipan besar ke tidak dipartisi large besar indeks mungkin tidak dicatat minimal karena pertidaksamaan P < I * 8 . Ketika P besar, perkiraan . yang besar juga jumlah baris yang disisipkan (I ) Dibutuhkan. Misalnya, indeks dengan 8 juta halaman tidak dapat mendukung logging minimal saat menyisipkan 1 juta baris atau kurang.

Indeks nonclustered

Pertimbangan dan perhitungan yang sama yang diterapkan pada indeks berkerumun di demo berlaku untuk tidak mengelompok indeks b-tree juga, selama indeks dikelola oleh operator paket khusus (lebar , atau per-indeks rencana). Indeks nonclustered dikelola oleh operator tabel dasar (mis. Indeks Clustered Insert ) tidak memenuhi syarat untuk FastLoadContext .

Perhatikan bahwa parameter rumus perlu dievaluasi lagi untuk setiap nonclustered operator indeks — ukuran baris yang dihitung, jumlah halaman indeks yang ada, dan perkiraan kardinalitas.

Keterangan umum

Hati-hati dengan perkiraan kardinalitas rendah di Indeks Sisipan operator, karena ini akan mempengaruhi I dan S parameter. Jika ambang tidak tercapai karena kesalahan estimasi kardinalitas, sisipan akan dilog sepenuhnya .

Ingat bahwa DMLRequestSort di-cache dengan paket — itu tidak dievaluasi pada setiap pelaksanaan rencana yang digunakan kembali. Ini dapat memperkenalkan bentuk Masalah Sensitivitas Parameter yang terkenal (juga dikenal sebagai "parameter sniffing").

Nilai P (halaman daun indeks) tidak disegarkan di awal setiap pernyataan. Implementasi saat ini menyimpan nilai untuk seluruh batch . Ini dapat memiliki efek samping yang tidak terduga. Misalnya, TRUNCATE TABLE dalam kelompok yang sama sebagai INSERT...SELECT tidak akan mengatur ulang P ke nol untuk perhitungan yang dijelaskan dalam artikel ini — mereka akan terus menggunakan nilai pra-pemotongan, dan kompilasi ulang tidak akan membantu. Solusinya adalah mengirimkan perubahan besar dalam kelompok terpisah.

Tanda Jejak

Dimungkinkan untuk memaksa FDemandRowsSortedForPerformance untuk mengembalikan benar dengan menyetel tidak berdokumen dan tidak didukung trace flag 2332, seperti yang saya tulis di Mengoptimalkan kueri T-SQL yang mengubah data. Saat TF 2332 aktif, jumlah perkiraan baris yang akan disisipkan masih harus setidaknya 100 . TF 2332 memengaruhi pembuatan log minimal keputusan untuk FastLoadContext saja (efektif untuk tumpukan yang dipartisi sejauh DMLRequestSort bersangkutan, tetapi tidak berpengaruh pada heap itu sendiri, karena FastLoadContext hanya berlaku untuk indeks).

Sebuah lebar/per-indeks bentuk rencana untuk pemeliharaan indeks nonclustered dapat dipaksakan untuk tabel rowstore menggunakan trace flag 8790 (tidak didokumentasikan secara resmi, tetapi disebutkan dalam artikel Basis Pengetahuan serta dalam artikel saya seperti yang ditautkan untuk TF2332 tepat di atas).

Semua oleh Sunil Agarwal dari tim SQL Server:

  • Apa yang dimaksud dengan Pengoptimalan Impor Massal?
  • Pengoptimalan Impor Massal (Logging Minimal)
  • Perubahan Logging Minimal di SQL Server 2008
  • Perubahan Logging Minimal di SQL Server 2008 (part-2)
  • Perubahan Logging Minimal di SQL Server 2008 (bagian-3)

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

  2. Cara Mendeklarasikan Pengecualian yang Ditentukan Pengguna Menggunakan PRAGMA EXCEPTION_INIT

  3. Penyimpanan Kueri:Menampilkan Dampak Indeks pada Sisipan

  4. SQL, cara memperbarui data

  5. SQL PILIH MIN