Perbedaan ini tampaknya hanya berlaku ketika objek adalah pohon B +. Ketika menghapus primary key
variabel di atas meja jadi tumpukan saya mendapat hasil berikut
2560
2120
2080
2130
2140
Tetapi dengan PK saya menemukan pola yang sama dalam tes saya juga dengan hasil khas di bawah ini.
+--------+--------+---------+-------------------+
| @table | #table | ##table | [permanent_table] |
+--------+--------+---------+-------------------+
| 2670 | 2683 | 9603 | 9703 |
| 6823 | 6840 | 9723 | 9790 |
| 6813 | 6816 | 9626 | 9703 |
| 6883 | 6816 | 9600 | 9716 |
| 6840 | 6856 | 9610 | 9673 |
+--------+--------+---------+-------------------+
Teori saya adalah bahwa ada beberapa optimasi yang tersedia ketika melakukan penyisipan massal ke pohon B + lokal sementara yang hanya berlaku ketika belum ada alokasi halaman.
Saya mendasarkan ini pada pengamatan berikut.
Saat menjalankan berbagai versi kode pengujian Anda, saya hanya melihat pola @table_variables
dan #temp
tabel ini. Bukan tabel permanen tempdb
atau ##
tabel.
Untuk mendapatkan kinerja yang lebih lambat, Anda tidak perlu menambahkan dan menghapus sebelumnya sejumlah besar baris dari tabel. Cukup menambahkan satu baris dan membiarkannya di sana sudah cukup.
TRUNCATE
alokasikan semua halaman dari tabel. DELETE
tidak akan menyebabkan halaman terakhir dalam tabel menjadi tidak dialokasikan.
Menggunakan profiler VS 2012 menunjukkan bahwa dalam kasus yang lebih cepat SQL Server menggunakan jalur kode yang berbeda. 36% dari waktu dihabiskan sqlmin.dll!RowsetBulk::InsertRow
vs 61% dari waktu yang dihabiskan sqlmin.dll!RowsetNewSS::InsertRow
untuk kasus yang lebih lambat.
Lari
SELECT *
FROM sys.dm_db_index_physical_stats(2,OBJECT_ID('tempdb..#values'),1,NULL, 'DETAILED')
setelah itu hapus kembali
+-------------+------------+--------------+--------------------+
| index_level | page_count | record_count | ghost_record_count |
+-------------+------------+--------------+--------------------+
| 0 | 1 | 0 | 1 |
| 1 | 1 | 1 | 0 |
| 2 | 1 | 1 | 0 |
+-------------+------------+--------------+--------------------+
Saya menemukan bahwa mungkin untuk mengurangi perbedaan waktu dengan mengaktifkan jejak flag 610 .
Ini memiliki efek mengurangi kuantitas penebangan secara substansial untuk menyisipkan berikutnya (turun dari 350 MB ke 103 MB karena tidak lagi log individu nilai-nilai baris dimasukkan) tapi ini hanya perbaikan kecil dalam timing untuk 2 dan selanjutnya @table
, #table
kasus dan kesenjangan masih ada. Bendera jejak meningkatkan kinerja umum menyisipkan ke dua jenis tabel lainnya secara signifikan.
+--------+--------+---------+-------------------+
| @table | #table | ##table | [permanent_table] |
+--------+--------+---------+-------------------+
| 2663 | 2670 | 5403 | 5426 |
| 5390 | 5396 | 5410 | 5403 |
| 5373 | 5390 | 5410 | 5403 |
| 5393 | 5410 | 5406 | 5433 |
| 5386 | 5396 | 5390 | 5420 |
+--------+--------+---------+-------------------+
Dari melihat log transaksi saya perhatikan bahwa sisipan awal terhadap tabel temporer lokal yang kosong tampaknya bahkan lebih sedikit dicatat (pada 96 MB).
Khususnya sisipan yang lebih cepat ini hanya memiliki 657
transaksi ( LOP_BEGIN_XACT
/ LOP_COMMIT_XACT
pasangan) dibandingkan dengan lebih 10,000
dalam kasus yang lebih lambat. Dalam LOP_FORMAT_PAGE
operasi tertentu tampak jauh berkurang. Kasing yang lebih lambat memiliki entri log transaksi untuk ini untuk setiap halaman dalam tabel (sekitar 10,270
) dibandingkan dengan 4
entri tersebut dalam kasing cepat.
Log yang digunakan dalam ketiga kasus adalah sebagai berikut (Saya telah menghapus catatan log untuk pembaruan ke tabel basis sistem untuk mengurangi jumlah teks tetapi mereka masih termasuk dalam total)
Memasukkan sisipan pertama terhadap @table_var
(96,5 MB)
+-----------------------+----------+----------------------------------------------+---------------+---------+
| Operation | Context | AllocUnitName | Size in Bytes | Cnt |
+-----------------------+----------+----------------------------------------------+---------------+---------+
| LOP_BEGIN_XACT | LCX_NULL | NULL | 83876 | 658 |
| LOP_COMMIT_XACT | LCX_NULL | NULL | 34164 | 657 |
| LOP_CREATE_ALLOCCHAIN | LCX_NULL | NULL | 120 | 3 |
| LOP_FORMAT_PAGE | LCX_HEAP | dbo.#531856C7 | 84 | 1 |
| LOP_FORMAT_PAGE | LCX_IAM | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 84 | 1 |
| LOP_FORMAT_PAGE | LCX_IAM | dbo.#531856C7 | 84 | 1 |
| LOP_FORMAT_PAGE | LCX_IAM | Unknown Alloc Unit | 84 | 1 |
| LOP_HOBT_DDL | LCX_NULL | NULL | 216 | 6 |
| LOP_HOBT_DELTA | LCX_NULL | NULL | 320 | 5 |
| LOP_IDENT_NEWVAL | LCX_NULL | NULL | 100240000 | 2506000 |
| LOP_INSERT_ROWS | LCX_HEAP | dbo.#531856C7 | 72 | 1 |
| LOP_MODIFY_ROW | LCX_IAM | dbo.#531856C7 | 88 | 1 |
| LOP_MODIFY_ROW | LCX_PFS | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 158592 | 1848 |
| LOP_MODIFY_ROW | LCX_PFS | dbo.#531856C7 | 80 | 1 |
| LOP_MODIFY_ROW | LCX_PFS | Unknown Alloc Unit | 216016 | 2455 |
| LOP_SET_BITS | LCX_GAM | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 84360 | 1406 |
| LOP_SET_BITS | LCX_GAM | Unknown Alloc Unit | 147120 | 2452 |
| LOP_SET_BITS | LCX_IAM | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 84360 | 1406 |
| LOP_SET_BITS | LCX_IAM | Unknown Alloc Unit | 147120 | 2452 |
| Total | NULL | NULL | 101209792 | 2519475 |
+-----------------------+----------+----------------------------------------------+---------------+---------+
Log off berikutnya memasukkan TF 610 off (350 MB)
+-----------------------+--------------------+----------------------------------------------+---------------+---------+
| Operation | Context | AllocUnitName | Size in Bytes | Cnt |
+-----------------------+--------------------+----------------------------------------------+---------------+---------+
| LOP_BEGIN_CKPT | LCX_NULL | NULL | 96 | 1 |
| LOP_BEGIN_XACT | LCX_NULL | NULL | 1520696 | 12521 |
| LOP_COMMIT_XACT | LCX_NULL | NULL | 651040 | 12520 |
| LOP_CREATE_ALLOCCHAIN | LCX_NULL | NULL | 40 | 1 |
| LOP_DELETE_SPLIT | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 2160 | 36 |
| LOP_END_CKPT | LCX_NULL | NULL | 136 | 1 |
| LOP_FORMAT_PAGE | LCX_HEAP | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 859236 | 10229 |
| LOP_FORMAT_PAGE | LCX_IAM | Unknown Alloc Unit | 84 | 1 |
| LOP_FORMAT_PAGE | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 3108 | 37 |
| LOP_HOBT_DDL | LCX_NULL | NULL | 648 | 18 |
| LOP_HOBT_DELTA | LCX_NULL | NULL | 657088 | 10267 |
| LOP_IDENT_NEWVAL | LCX_NULL | NULL | 100239960 | 2505999 |
| LOP_INSERT_ROWS | LCX_CLUSTERED | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 258628000 | 2506000 |
| LOP_INSERT_ROWS | LCX_HEAP | dbo.#531856C7 | 72 | 1 |
| LOP_INSERT_ROWS | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 1042776 | 10302 |
| LOP_MODIFY_HEADER | LCX_HEAP | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 859236 | 10229 |
| LOP_MODIFY_HEADER | LCX_INDEX_INTERIOR | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 3192 | 38 |
| LOP_MODIFY_ROW | LCX_IAM | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 704 | 8 |
| LOP_MODIFY_ROW | LCX_PFS | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 934264 | 11550 |
| LOP_MODIFY_ROW | LCX_PFS | Unknown Alloc Unit | 783984 | 8909 |
| LOP_SET_BITS | LCX_GAM | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 76980 | 1283 |
| LOP_SET_BITS | LCX_GAM | Unknown Alloc Unit | 534480 | 8908 |
| LOP_SET_BITS | LCX_IAM | dbo.#4F47C5E3.PK__#4F47C5E__3213E83F51300E55 | 76980 | 1283 |
| LOP_SET_BITS | LCX_IAM | Unknown Alloc Unit | 534480 | 8908 |
| LOP_SHRINK_NOOP | LCX_NULL | NULL | 32 | 1 |
| LOP_XACT_CKPT | LCX_NULL | NULL | 92 | 1 |
| Total | NULL | NULL | 367438748 | 5119297 |
+-----------------------+--------------------+----------------------------------------------+---------------+---------+
Mencatat sisipan TF 610 pada (103 MB) berikutnya
+-------------------------+-------------------------+----------------------------------------------+---------------+---------+
| Operation | Context | AllocUnitName | Size in Bytes | Cnt |
+-------------------------+-------------------------+----------------------------------------------+---------------+---------+
| LOP_BEGIN_CKPT | LCX_NULL | NULL | 192 | 2 |
| LOP_BEGIN_XACT | LCX_NULL | NULL | 1339796 | 11099 |
| LOP_BULK_EXT_ALLOCATION | LCX_NULL | NULL | 20616 | 162 |
| LOP_COMMIT_XACT | LCX_NULL | NULL | 577096 | 11098 |
| LOP_CREATE_ALLOCCHAIN | LCX_NULL | NULL | 40 | 1 |
| LOP_DELETE_SPLIT | LCX_INDEX_INTERIOR | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 2160 | 36 |
| LOP_END_CKPT | LCX_NULL | NULL | 272 | 2 |
| LOP_FORMAT_PAGE | LCX_BULK_OPERATION_PAGE | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 863520 | 10280 |
| LOP_FORMAT_PAGE | LCX_IAM | Unknown Alloc Unit | 84 | 1 |
| LOP_FORMAT_PAGE | LCX_INDEX_INTERIOR | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 3108 | 37 |
| LOP_HOBT_DELTA | LCX_NULL | NULL | 666496 | 10414 |
| LOP_IDENT_NEWVAL | LCX_NULL | NULL | 100239960 | 2505999 |
| LOP_INSERT_ROWS | LCX_CLUSTERED | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 23544 | 218 |
| LOP_INSERT_ROWS | LCX_HEAP | dbo.#719CDDE7 | 72 | 1 |
| LOP_INSERT_ROWS | LCX_INDEX_INTERIOR | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 1042776 | 10302 |
| LOP_MODIFY_HEADER | LCX_BULK_OPERATION_PAGE | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 780216 | 10266 |
| LOP_MODIFY_HEADER | LCX_HEAP | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 1718472 | 20458 |
| LOP_MODIFY_HEADER | LCX_INDEX_INTERIOR | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 3192 | 38 |
| LOP_MODIFY_ROW | LCX_IAM | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 704 | 8 |
| LOP_MODIFY_ROW | LCX_PFS | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 114832 | 1307 |
| LOP_MODIFY_ROW | LCX_PFS | Unknown Alloc Unit | 231696 | 2633 |
| LOP_RANGE_INSERT | LCX_NULL | NULL | 48 | 1 |
| LOP_SET_BITS | LCX_GAM | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 77100 | 1285 |
| LOP_SET_BITS | LCX_GAM | Unknown Alloc Unit | 157920 | 2632 |
| LOP_SET_BITS | LCX_IAM | dbo.#6DCC4D03.PK__#6DCC4D0__3213E83F6FB49575 | 77100 | 1285 |
| LOP_SET_BITS | LCX_IAM | Unknown Alloc Unit | 157920 | 2632 |
| LOP_XACT_CKPT | LCX_NULL | NULL | 92 | 1 |
| Total | NULL | NULL | 108102960 | 2602218 |
+-------------------------+-------------------------+----------------------------------------------+---------------+---------+
TRUNCATE
lebihDELETE
dari itu sendiri juga akan berdebat untuk itu. Saya juga jarang mempertimbangkan variabel tabel untuk sejumlah besar baris.10,000+
halaman yang terjadi dengan cara yang jauh lebih dioptimalkan dan tampaknya menghindari beberapa overhead per halaman. Untuk sisipan yang lebih kecil saya berharap perbedaan seperti itu menjadi kurang signifikan.Pengamatan dan spekulasi. . .
Pada beberapa sistem, CURRENT_TIMESTAMP didefinisikan sebagai waktu di awal transaksi saat ini. Pencarian cepat tidak menemukan dokumentasi pasti tentang bagaimana CURRENT_TIMESTAMP berperilaku pada SQL Server. Tetapi mode default SQL Server adalah untuk autocommit transaksi, dan tidak ada TRANSAKSI BEGIN di sini, jadi itu harus waktu tepat sebelum pernyataan INSERT. (Pernyataan DELETE harus secara otomatis melakukan, dan dengan cara apa pun CURRENT_TIMESTAMP bekerja pada SQL Server, seharusnya tidak ada hubungannya dengan pernyataan DELETE ketika Anda menggunakan transaksi yang dilakukan secara otomatis.)
Pada iterasi pertama, pernyataan DELETE tidak memiliki pekerjaan nyata untuk dilakukan, dan tidak ada baris individu untuk dicatat. Mungkin pengoptimal tahu itu, dan itu mengurangi waktu untuk iterasi pertama. (Kombinasi tanpa baris untuk dihapus, dan tidak ada baris untuk dicatat.)
Anda bisa mengujinya (saya pikir) dengan memasukkan sebelum menghapus.
sumber