Bagikan melalui


Database sampel untuk OLTP dalam memori

Berlaku untuk: SQL ServerAzure SQL Database

Gambaran Umum

Sampel ini menampilkan fitur OLTP dalam memori. Ini menunjukkan tabel yang dioptimalkan memori dan prosedur tersimpan yang dikompilasi secara asli, dan dapat digunakan untuk menunjukkan manfaat performa OLTP dalam memori.

Catatan

Untuk melihat artikel ini untuk SQL Server 2014 (12.x), lihat Ekstensi ke AdventureWorks untuk Menunjukkan In-Memory OLTP.

Sampel ini memigrasikan lima tabel dalam database AdventureWorks2025 ke memori yang dioptimalkan, serta mencakup beban kerja demo untuk pengolahan pesanan penjualan. Anda dapat menggunakan beban kerja demo ini untuk melihat manfaat performa menggunakan OLTP dalam memori di server Anda.

Dalam deskripsi sampel, kita membahas pertukaran yang dibuat dalam memigrasikan tabel ke OLTP dalam memori untuk memperhitungkan fitur-fitur yang belum didukung untuk tabel yang dioptimalkan untuk memori.

Dokumentasi sampel ini disusun sebagai berikut:

Prasyarat

  • SQL Server 2016 (13.x)

  • Untuk pengujian performa, server dengan spesifikasi yang mirip dengan lingkungan produksi Anda. Untuk sampel khusus ini, Anda harus memiliki setidaknya 16 GB memori yang tersedia untuk SQL Server. Untuk panduan umum tentang perangkat keras untuk OLTP dalam memori, lihat posting blog berikut: Pertimbangan perangkat keras untuk In-Memory OLTP di SQL Server

Menginstal sampel OLTP dalam memori berdasarkan AdventureWorks

Ikuti langkah-langkah berikut untuk menginstal sampel:

  1. Unduh AdventureWorks2016_EXT.bak dan SQLServer2016Samples.zip dari: https://github.com/microsoft/sql-server-samples/releases/tag/adventureworks ke folder lokal, misalnya C:\Temp.

  2. Pulihkan cadangan database menggunakan Transact-SQL atau SQL Server Management Studio:

    1. Identifikasi folder target dan nama file untuk file data, misalnya:

      H:\DATA\AdventureWorks2022_Data.mdf
      
    2. Identifikasi folder target dan nama file untuk file log, misalnya:

      I:\DATA\AdventureWorks2022_log.ldf
      
      1. File log harus ditempatkan pada drive yang berbeda dari file data, idealnya drive latensi rendah seperti penyimpanan SSD atau PCIe, untuk performa maksimum.

    Contoh skrip T-SQL:

    RESTORE DATABASE [AdventureWorks2022]
      FROM DISK = N'C:\temp\AdventureWorks2022.bak'
        WITH FILE = 1,
      MOVE N'AdventureWorks2022_Data' TO N'h:\DATA\AdventureWorks2022_Data.mdf',
      MOVE N'AdventureWorks2022_Log' TO N'i:\DATA\AdventureWorks2022_log.ldf',
      MOVE N'AdventureWorks2022_mod' TO N'h:\data\AdventureWorks2022_mod'
     GO
    
  3. Untuk melihat contoh skrip dan beban kerja, bongkar file SQLServer2016Samples.zip ke folder lokal. Lihat file In-Memory OLTP\readme.txt untuk petunjuk tentang menjalankan beban kerja.

Deskripsi tabel dan prosedur sampel

Sampel membuat tabel baru untuk produk dan pesanan penjualan, berdasarkan tabel yang ada di AdventureWorks2025. Skema tabel baru mirip dengan tabel yang ada, dengan beberapa perbedaan, seperti yang dijelaskan nanti di bagian ini.

Tabel yang dioptimalkan untuk memori baru memiliki akhiran _inmem. Sampel juga mencakup tabel terkait yang membawa akhiran _ondisk - tabel ini dapat digunakan untuk membuat perbandingan satu-ke-satu antara performa tabel yang dioptimalkan memori dan tabel berbasis disk pada sistem Anda.

Tabel yang dioptimalkan memori yang digunakan dalam beban kerja untuk perbandingan performa sepenuhnya tahan lama dan sepenuhnya dicatat. Mereka tidak mengorbankan durabilitas atau keandalan untuk mencapai perolehan performa.

Beban kerja target untuk sampel ini adalah pemrosesan pesanan penjualan, di mana kami mempertimbangkan juga informasi tentang produk dan diskon. Untuk akhir ini, kita menggunakan tabel SalesOrderHeader, , SalesOrderDetail, ProductSpecialOffer, dan SpecialOfferProduct.

Dua prosedur tersimpan baru, Sales.usp_InsertSalesOrder_inmem dan Sales.usp_UpdateSalesOrderShipInfo_inmem, digunakan untuk menyisipkan pesanan penjualan dan untuk memperbarui informasi pengiriman pesanan penjualan tertentu.

Skema Demo baru berisi tabel pembantu dan prosedur tersimpan untuk menjalankan beban kerja demo.

Secara konkret, sampel OLTP Dalam Memori menambahkan objek berikut ke AdventureWorks2025:

Tabel ditambahkan oleh sampel

Tabel baru

Sales.SalesOrderHeader_inmem

  • Informasi utama tentang pesanan penjualan. Setiap pesanan penjualan memiliki satu baris dalam tabel ini.

Sales.SalesOrderDetail_inmem

  • Detail pesanan penjualan. Setiap item pesanan penjualan ditampilkan dalam satu baris dalam tabel ini.

Sales.SpecialOffer_inmem

  • Informasi tentang penawaran khusus, termasuk persentase diskon yang terkait dengan setiap penawaran khusus.

Sales.SpecialOfferProduct_inmem

  • Tabel referensi antara penawaran khusus dan produk. Setiap penawaran khusus dapat menampilkan nol atau lebih produk, dan setiap produk dapat ditampilkan dalam nol atau lebih penawaran khusus.

Production.Product_inmem

  • Informasi tentang produk, termasuk harga eceran.

Demo.DemoSalesOrderDetailSeed

  • Digunakan dalam beban kerja demo untuk membuat pesanan penjualan sampel.

Variasi tabel berbasis disk:

  • Sales.SalesOrderHeader_ondisk

  • Sales.SalesOrderDetail_ondisk

  • Sales.SpecialOffer_ondisk

  • Sales.SpecialOfferProduct_ondisk

  • Production.Product_ondisk

Perbedaan antara tabel berbasis disk asli dan yang dioptimalkan memori baru

Biasanya, tabel baru yang diperkenalkan oleh sampel ini menggunakan kolom yang sama dan jenis data yang sama dengan tabel asli. Namun, ada beberapa perbedaan. Kami mencantumkan perbedaan di bagian ini, bersama dengan alasan untuk perubahan.

Sales.SalesOrderHeader_inmem

  • Batasan default didukung untuk tabel yang dioptimalkan memori, dan sebagian besar batasan default yang kami migrasikan apa adanya. Namun, tabel Sales.SalesOrderHeader asli berisi dua batasan default yang mengambil tanggal saat ini, untuk kolom OrderDate dan ModifiedDate. Dalam pemrosesan pesanan dengan throughput tinggi dan tingkat konkurensi yang tinggi, sumber daya global apa pun dapat menjadi titik perebutan. Waktu sistem merupakan sumber daya global, dan kami telah mengamati bahwa itu dapat menjadi kendala saat menjalankan beban kerja OLTP In-Memory yang memasukkan pesanan penjualan, terutama jika waktu sistem perlu diambil untuk beberapa kolom di bagian kepala dan detail pesanan penjualan. Masalah ditangani dalam sampel ini dengan mengambil waktu sistem sekali saja setiap kali pesanan penjualan dimasukkan, serta menggunakan nilai itu untuk kolom tanggal waktu di SalesOrderHeader_inmem dan SalesOrderDetail_inmem, dalam prosedur tersimpan Sales.usp_InsertSalesOrder_inmem.

  • Alias jenis data yang ditentukan pengguna (UDT) - Tabel asli menggunakan dua alias UDT dbo.OrderNumber dan dbo.AccountNumber, untuk kolom PurchaseOrderNumber dan AccountNumber, masing-masing. SQL Server 2016 (13.x) tidak mendukung alias UDT untuk tabel yang dioptimalkan memori, sehingga tabel baru menggunakan jenis data sistem nvarchar(25) dan nvarchar(15), masing-masing.

  • Kolom yang dapat diubah ke null dalam kunci indeks - Dalam tabel asli, kolom SalesPersonID dapat diubah ke null, sementara dalam tabel baru kolom tidak dapat diubah ke null dan memiliki batasan default dengan nilai (-1). Keadaan ini karena indeks pada tabel yang dioptimalkan memori tidak dapat memiliki kolom yang dapat diubah ke null di kunci indeks; -1 adalah pengganti null dalam hal ini.

  • Kolom komputasi - Kolom SalesOrderNumber komputasi dan TotalDue dihilangkan, karena SQL Server 2016 (13.x) tidak mendukung kolom komputasi dalam tabel yang dioptimalkan memori. Tampilan Sales.vSalesOrderHeader_extended_inmem baru mencerminkan kolom SalesOrderNumber dan TotalDue. Oleh karena itu, Anda dapat menggunakan tampilan ini jika kolom ini diperlukan.

    • Berlaku untuk: SQL Server 2017 (14.x). Dimulai dengan SQL Server 2017 (14.x), kolom komputasi didukung dalam tabel dan indeks yang dioptimalkan memori.
  • Batasan kunci asing didukung untuk tabel yang dioptimalkan memori di SQL Server 2016 (13.x), tetapi hanya jika tabel yang dirujuk juga dioptimalkan memori. Kunci asing yang mereferensikan tabel yang juga dimigrasikan ke memori yang dioptimalkan disimpan dalam tabel yang dimigrasikan, sementara kunci asing lainnya dihilangkan. Selain itu, SalesOrderHeader_inmem adalah tabel panas dalam contoh beban kerja, dan batasan kunci asing memerlukan pemrosesan ekstra untuk semua operasi DML, karena memerlukan pencarian di semua tabel lain yang dirujuk dalam batasan ini. Oleh karena itu, asumsinya adalah bahwa aplikasi memastikan integritas referensial untuk Sales.SalesOrderHeader_inmem tabel, dan integritas referensial tidak divalidasi saat baris dimasukkan.

  • Rowguid - Kolom rowguid dihilangkan. Meskipun uniqueidentifier didukung untuk tabel yang dioptimalkan memori, opsi ROWGUIDCOL tidak didukung di SQL Server 2016 (13.x). Kolom semacam ini biasanya digunakan untuk menggabungkan replikasi atau tabel yang memiliki kolom aliran file. Sampel ini tidak mencakup keduanya.

Penjualan.DetailPesananPenjualan

  • Batasan default - mirip dengan SalesOrderHeader, batasan default yang memerlukan tanggal/waktu sistem tidak dimigrasikan. Sebagai gantinya, prosedur tersimpan yang memasukkan pesanan penjualan mengelola penyisipan tanggal/waktu sistem saat ini saat penyisipan pertama.

  • Kolom komputasi - kolom LineTotal komputasi tidak dimigrasikan karena kolom komputasi tidak didukung dengan tabel yang dioptimalkan memori di SQL Server 2016 (13.x). Untuk mengakses kolom ini, gunakan tampilan Sales.vSalesOrderDetail_extended_inmem.

  • Rowguid - Kolom rowguid dihilangkan. Untuk detailnya, lihat deskripsi untuk tabel SalesOrderHeader.

Produksi.Produk

  • Alias UDT - tabel asli menggunakan jenis data yang ditentukan pengguna dbo.Flag, yang setara dengan jenis data sistem bit. Tabel yang dimigrasikan menggunakan jenis data bit sebagai gantinya.

  • Rowguid - Kolom rowguid dihilangkan. Untuk detailnya, lihat deskripsi untuk tabel SalesOrderHeader.

Penjualan.PenawaranKhusus

  • Rowguid - Kolom rowguid dihilangkan. Untuk detailnya, lihat deskripsi untuk tabel SalesOrderHeader.

Sales.SpecialOfferProduct

  • Rowguid - Kolom rowguid dihilangkan. Untuk detailnya, lihat deskripsi untuk tabel SalesOrderHeader.

Pertimbangan untuk indeks pada tabel yang dioptimalkan memori

Indeks garis besar untuk tabel yang dioptimalkan memori adalah indeks NONCLUSTERED, yang mendukung pencarian titik (pencarian indeks pada predikat kesetaraan), pemindaian rentang (pencarian indeks dalam predikat ketidaksetaraan), pemindaian indeks penuh, dan pemindaian yang diurutkan. Selain itu, indeks NONCLUSTERED mendukung pencarian pada kolom utama kunci indeks. Bahkan indeks NONCLUSTERED yang dioptimalkan memori mendukung semua operasi yang didukung oleh indeks NONCLUSTERED berbasis disk, dengan satu-satunya pengecualian adalah pemindaian mundur. Oleh karena itu, menggunakan indeks NONCLUSTERED adalah pilihan yang aman untuk indeks Anda.

Indeks HASH dapat digunakan untuk mengoptimalkan beban kerja lebih lanjut. Mereka dioptimalkan untuk pencarian data spesifik dan penyisipan baris. Namun, seseorang harus mempertimbangkan bahwa mereka tidak mendukung pemindaian rentang, pemindaian terurut, atau pencarian pada kolom kunci indeks utama. Oleh karena itu, kehati-hatian perlu dilakukan saat menggunakan indeks ini. Selain itu, perlu untuk menentukan bucket_count pada waktu pembuatan. Biasanya harus diatur di antara satu dan dua kali jumlah nilai kunci indeks, tetapi menilai berlebihan biasanya bukan masalah.

Untuk informasi selengkapnya:

Indeks pada tabel yang dimigrasikan disetel untuk beban kerja pemrosesan pesanan penjualan demo. Beban kerja bergantung pada sisipan dan pencarian titik dalam tabel Sales.SalesOrderHeader_inmem dan Sales.SalesOrderDetail_inmem, dan juga bergantung pada pencarian titik pada kolom kunci utama dalam tabel Production.Product_inmem dan Sales.SpecialOffer_inmem.

Sales.SalesOrderHeader_inmem memiliki tiga indeks, semuanya merupakan indeks HASH untuk alasan kinerja, dan karena tidak diperlukan pemindaian terurut atau berbasis rentang untuk beban kerja ini.

  • Indeks HASH pada (SalesOrderID): bucket_count berukuran 10 juta (dibulatkan hingga 16 juta), karena jumlah pesanan penjualan yang diharapkan adalah 10 juta

  • Indeks HASH pada (SalesPersonID): bucket_count adalah 1 juta. Himpunan data yang disediakan tidak banyak memiliki tenaga penjualan. Tetapi bucket_count besar ini memungkinkan pertumbuhan di masa depan. Selain itu, Anda tidak membayar penalti performa untuk pencarian titik jika bucket_count terlalu besar.

  • Indeks HASH pada (CustomerID): bucket_count adalah 1 juta. Himpunan data yang disediakan tidak memiliki banyak pelanggan, tetapi ini memungkinkan pertumbuhan di masa mendatang.

Sales.SalesOrderDetail_inmem memiliki tiga indeks, semuanya merupakan indeks HASH untuk alasan kinerja, dan karena tidak diperlukan pemindaian terurut atau berbasis rentang untuk beban kerja ini.

  • Indeks HASH pada (SalesOrderID, SalesOrderDetailID): ini adalah indeks kunci utama, dan meskipun pencarian pada (SalesOrderID, SalesOrderDetailID) jarang, menggunakan indeks hash untuk kunci mempercepat sisipan baris. bucket_count berukuran 50 juta (dibulatkan ke atas menjadi 67 juta): jumlah pesanan penjualan yang diharapkan adalah 10 juta, dan dirancang untuk memiliki rata-rata lima barang per pesanan

  • Indeks HASH pada (SalesOrderID): pencarian berdasarkan pesanan penjualan sering terjadi: Anda ingin menemukan semua item baris yang berhubungan dengan satu pesanan. bucket_count berukuran 10 juta (dibulatkan hingga 16 juta), karena jumlah pesanan penjualan yang diharapkan adalah 10 juta

  • Indeks HASH pada (ProductID): bucket_count adalah 1 juta. Himpunan data yang disediakan tidak memiliki banyak produk, tetapi ini memungkinkan pertumbuhan di masa mendatang.

Production.Product_inmem memiliki tiga indeks

  • Indeks HASH pada (ProductID): pencarian pada ProductID berada di jalur kritis untuk beban kerja demo, sehingga ini adalah indeks hash.

  • Indeks NONCLUSTERED pada (Name): ini memungkinkan pemindaian terurut dari nama produk

  • Indeks NONCLUSTERED pada (ProductNumber): ini memungkinkan pencarian terurut nomor produk

Sales.SpecialOffer_inmem memiliki satu indeks HASH pada (SpecialOfferID): pencarian titik penawaran khusus berada di bagian penting dari beban kerja demo. bucket_count memiliki ukuran 1 juta untuk memungkinkan pertumbuhan di masa depan.

Sales.SpecialOfferProduct_inmem tidak direferensikan dalam beban kerja demo, dan dengan demikian tidak ada kebutuhan yang jelas untuk menggunakan indeks hash pada tabel ini untuk mengoptimalkan beban kerja - indeks pada (SpecialOfferID, ProductID) dan (ProductID) adalah NONCLUSTERED.

Dalam contoh sebelumnya, beberapa jumlah wadah berukuran besar, tetapi tidak jumlah wadah untuk indeks pada SalesOrderHeader_inmem dan SalesOrderDetail_inmem: mereka berukuran hanya untuk 10 juta pesanan penjualan. Ini dilakukan untuk memungkinkan penginstalan contoh pada sistem dengan memori yang rendah, meskipun dalam kasus tersebut beban kerja demo gagal dengan kesalahan kehabisan memori. Jika Anda ingin menskalakan jauh lebih dari 10 juta pesanan penjualan, jangan ragu untuk meningkatkan jumlah wadah yang sesuai.

Pertimbangan untuk pemanfaatan memori

Pemanfaatan memori dalam database sampel, baik sebelum dan sesudah menjalankan beban kerja demo, dibahas dalam Bagian Pemanfaatan Memori untuk tabel yang dioptimalkan memori.

Prosedur tersimpan ditambahkan oleh sampel

Dua prosedur tersimpan utama untuk menyisipkan pesanan penjualan dan memperbarui detail pengiriman adalah sebagai berikut:

  • Sales.usp_InsertSalesOrder_inmem

    • Menyisipkan pesanan penjualan baru ke dalam database dan menghasilkan keluaran SalesOrderID untuk pesanan penjualan tersebut. Sebagai parameter input, diperlukan detail untuk header pesanan penjualan, dan item baris dalam pesanan tersebut.

    • Parameter keluaran

      • @SalesOrderID int - SalesOrderID untuk pesanan penjualan yang baru saja dimasukkan
    • Parameter masukan yang diperlukan:

      • @DueDatedatetime2
      • @CustomerIDint
      • @BillToAddressIDint
      • @ShipToAddressIDint
      • @ShipMethodIDint
      • Sales.SalesOrderDetailType_inmem@SalesOrderDetails - parameter bernilai tabel (TVP) yang berisi item baris pesanan
    • Parameter masukan (opsional):

      • @Statustinyint
      • @OnlineOrderFlagbit
      • @PurchaseOrderNumbernvarchar(25)
      • @AccountNumbernvarchar(15)
      • @SalesPersonIDint
      • @TerritoryIDint
      • @CreditCardIDint
      • @CreditCardApprovalCodevarchar(15)
      • @CurrencyRateIDint
      • @Commentnvarchar(128)
  • Sales.usp_UpdateSalesOrderShipInfo_inmem

    • Perbarui informasi pengiriman untuk pesanan penjualan tertentu. Ini juga memperbarui informasi pengiriman untuk semua item-item pesanan penjualan.

    • Ini adalah prosedur pembungkus Sales.usp_UpdateSalesOrderShipInfo_native untuk prosedur tersimpan yang dikompilasi secara asli dengan logika coba lagi untuk menangani potensi konflik (tidak terduga) dengan transaksi bersamaan yang memperbarui urutan yang sama. Untuk informasi selengkapnya, lihat logika coba lagi.

  • Sales.usp_UpdateSalesOrderShipInfo_native

    • Ini adalah prosedur tersimpan yang dikompilasi secara asli yang benar-benar memproses pembaruan untuk informasi pengiriman. Ini dimaksudkan untuk dipanggil dari prosedur pembungkus tersimpan Sales.usp_UpdateSalesOrderShipInfo_inmem. Jika klien dapat menangani kegagalan dan menerapkan logika ulang, Anda dapat memanggil prosedur ini secara langsung, daripada menggunakan prosedur pembungkus yang tersimpan.

Prosedur tersimpan berikut ini digunakan untuk beban kerja demo.

  • Demo.usp_DemoReset

    • Mengatur ulang demo dengan mengosongkan dan mengisi ulang tabel SalesOrderHeader dan SalesOrderDetail.

Prosedur tersimpan berikut digunakan untuk menyisipkan dan menghapus dari tabel yang dioptimalkan memori sambil menjamin domain dan integritas referensial.

  • Production.usp_InsertProduct_inmem
  • Production.usp_DeleteProduct_inmem
  • Sales.usp_InsertSpecialOffer_inmem
  • Sales.usp_DeleteSpecialOffer_inmem
  • Sales.usp_InsertSpecialOfferProduct_inmem

Akhirnya prosedur tersimpan berikut digunakan untuk memverifikasi domain dan integritas referensial.

  1. dbo.usp_ValidateIntegrity

    • Parameter opsional: @object_id - ID objek untuk memvalidasi integritas untuk

    • Prosedur ini bergantung pada tabel dbo.DomainIntegrity, , dbo.ReferentialIntegritydan dbo.UniqueIntegrity untuk aturan integritas yang perlu diverifikasi - sampel mengisi tabel ini berdasarkan pemeriksaan, kunci asing, dan batasan unik yang ada untuk tabel asli dalam AdventureWorks2025 database.

    • Ini bergantung pada prosedur dbo.usp_GenerateCKCheckpembantu , , dbo.usp_GenerateFKCheckdan dbo.GenerateUQCheck untuk menghasilkan T-SQL yang diperlukan untuk melakukan pemeriksaan integritas.

Pengukuran performa menggunakan beban kerja demo

ostress adalah alat baris perintah yang dikembangkan oleh tim dukungan Microsoft CSS SQL Server. Alat ini dapat digunakan untuk menjalankan kueri atau menjalankan prosedur tersimpan secara paralel. Anda dapat mengonfigurasi jumlah utas untuk menjalankan pernyataan T-SQL tertentu secara paralel, dan Anda dapat menentukan berapa kali pernyataan harus dijalankan pada utas ini; ostress memutar utas dan menjalankan pernyataan pada semua utas secara paralel. Setelah eksekusi selesai untuk semua utas, ostress melaporkan waktu yang diperlukan untuk semua utas untuk menyelesaikan eksekusi.

Pasang ostress

ostress diinstal sebagai bagian dari Utilitas Report Markup Language (RML) ; tidak ada penginstalan mandiri untuk ostress.

Langkah-langkah penginstalan:

  1. Unduh dan jalankan paket penginstalan x64 untuk utilitas RML dari halaman berikut: Unduh RML untuk SQL Server

  2. Jika ada kotak dialog yang mengatakan file tertentu sedang digunakan, pilih 'Lanjutkan'

Jalankan ostress

Ostress dijalankan dari baris perintah. Paling nyaman untuk menjalankan alat dari RML Cmd Prompt, yang diinstal sebagai bagian dari Utilitas RML.

Untuk membuka Prompt Cmd RML, ikuti instruksi berikut:

Di Windows, buka menu mulai dengan memilih kunci Windows, dan ketik rml. Pilih Perintah Cmd RML, yang ada dalam daftar hasil pencarian.

Pastikan bahwa command prompt terletak di direktori penginstalan Utilitas RML.

Opsi baris perintah untuk ostress dapat dilihat saat hanya berjalan ostress.exe tanpa opsi baris perintah apa pun. Opsi utama yang perlu dipertimbangkan untuk menjalankan ostress dengan sampel ini adalah sebagai berikut:

Option Description
-S Nama instans SQL Server untuk disambungkan.
-E Gunakan autentikasi Windows untuk menyambungkan (default); jika Anda menggunakan autentikasi SQL Server, gunakan opsi -U dan -P untuk menentukan nama pengguna dan kata sandi.
-d Nama database, untuk contoh AdventureWorks2025ini .
-Q Pernyataan T-SQL yang akan dijalankan.
-n Jumlah koneksi yang memproses setiap file/kueri input.
-r Jumlah iterasi untuk setiap koneksi untuk menjalankan setiap file/kueri input.

Beban kerja demo

Prosedur tersimpan utama yang digunakan dalam beban kerja demo adalah Sales.usp_InsertSalesOrder_inmem/ondisk. Skrip dalam contoh berikut membangun parameter bertipe tabel (TVP) dengan data sampel, dan memanggil prosedur untuk memasukkan pesanan penjualan dengan lima item baris.

Alat ostress digunakan untuk menjalankan panggilan prosedur tersimpan secara paralel, untuk mensimulasikan klien yang menyisipkan pesanan penjualan secara bersamaan.

Setel ulang demo setelah setiap kali menjalankan stres Demo.usp_DemoReset. Prosedur ini menghapus baris dalam tabel yang dioptimalkan memori, memotong tabel berbasis disk, dan menjalankan titik pemeriksaan database.

Skrip berikut dijalankan secara bersamaan untuk mensimulasikan beban kerja pemrosesan pesanan penjualan:

DECLARE @i AS INT = 0, @od AS Sales.SalesOrderDetailType_inmem, @SalesOrderID AS INT, @DueDate AS DATETIME2 = sysdatetime(), @CustomerID AS INT = RAND() * 8000, @BillToAddressID AS INT = RAND() * 10000, @ShipToAddressID AS INT = RAND() * 10000, @ShipMethodID AS INT = (RAND() * 5) + 1;
INSERT INTO @od
SELECT OrderQty,
       ProductID,
       SpecialOfferID
FROM Demo.DemoSalesOrderDetailSeed
WHERE OrderID = CAST ((RAND() * 106) + 1 AS INT);
WHILE (@i < 20)
    BEGIN
        EXECUTE Sales.usp_InsertSalesOrder_inmem
            @SalesOrderID OUTPUT,
            @DueDate,
            @CustomerID,
            @BillToAddressID,
            @ShipToAddressID,
            @ShipMethodID,
            @od;
        SET @i + = 1;
    END

Dengan skrip ini, setiap urutan sampel yang dibangun dimasukkan 20 kali, melalui 20 prosedur tersimpan yang dijalankan dalam perulangan WHILE. Perulangan digunakan untuk memperhitungkan fakta bahwa database digunakan untuk membuat urutan sampel. Di lingkungan produksi yang khas, aplikasi tingkat menengah membangun pesanan penjualan yang akan dimasukkan.

Skrip sebelumnya menyisipkan pesanan penjualan ke dalam tabel yang dioptimalkan memori. Skrip untuk memasukkan pesanan penjualan ke dalam tabel berbasis disk diturunkan dengan mengganti dua kemunculan _inmem dengan _ondisk.

Kami menggunakan alat ostress untuk menjalankan skrip menggunakan beberapa koneksi bersamaan. Kami menggunakan parameter -n untuk mengontrol jumlah koneksi, dan parameter r untuk mengontrol berapa kali skrip dijalankan pada setiap koneksi.

Menjalankan beban kerja

Untuk menguji dalam skala besar, kami menyisipkan 10 juta pesanan penjualan, menggunakan 100 koneksi. Pengujian ini berjalan secara wajar pada server sederhana (misalnya, 8 inti fisik, 16 inti logis), dan penyimpanan SSD dasar untuk penyimpanan log. Jika pengujian tidak berkinerja baik pada perangkat keras Anda, lihat bagian Memecahkan masalah pengujian yang berjalan lambat. Jika Anda ingin mengurangi tingkat stres untuk pengujian ini, turunkan jumlah koneksi dengan mengubah parameter -n. Misalnya untuk menurunkan jumlah koneksi menjadi 40, ubah parameter -n100 menjadi -n40.

Sebagai ukuran performa untuk beban kerja, kami menggunakan waktu yang berlalu seperti yang dilaporkan oleh ostress.exe setelah menjalankan beban kerja.

Instruksi dan pengukuran berikut menggunakan beban kerja yang menyisipkan 10 juta pesanan penjualan. Untuk instruksi menjalankan beban kerja yang dikurangi dengan menyisipkan 1 juta pesanan penjualan, lihat instruksi dalam In-Memory OLTP\readme.txt yang masuk dalam arsip SQLServer2016Samples.zip.

Tabel yang dioptimalkan untuk memori

Kita mulai dengan menjalankan beban kerja pada tabel yang dioptimalkan memori. Perintah berikut membuka 100 utas, masing-masing berjalan untuk 5.000 iterasi. Setiap iterasi menyisipkan 20 pesanan penjualan dalam transaksi terpisah. Ada 20 sisipan per iterasi untuk mengimbangi fakta bahwa database digunakan untuk menghasilkan data yang akan dimasukkan. Hasil ini menghasilkan total 20 * 5.000 * 100 = 10.000.000 sisipan pesanan penjualan.

Buka Prompt Cmd RML, dan jalankan perintah berikut:

Pilih tombol Salin untuk menyalin perintah, dan tempelkan ke prompt perintah Utilitas RML.

ostress.exe -n100 -r5000 -S. -E -dAdventureWorks2022 -q -Q"DECLARE @i AS INT = 0, @od AS Sales.SalesOrderDetailType_inmem, @SalesOrderID AS INT, @DueDate AS DATETIME2 = SYSDATETIME(), @CustomerID AS INT = RAND() * 8000, @BillToAddressID AS INT = RAND() * 10000, @ShipToAddressID AS INT = RAND() * 10000, @ShipMethodID AS INT = (RAND() * 5) + 1; INSERT INTO @od SELECT OrderQty, ProductID, SpecialOfferID FROM Demo.DemoSalesOrderDetailSeed WHERE OrderID = CAST ((RAND() * 106) + 1 AS INT); WHILE (@i < 20) BEGIN EXECUTE Sales.usp_InsertSalesOrder_inmem @SalesOrderID OUTPUT, @DueDate, @CustomerID, @BillToAddressID, @ShipToAddressID, @ShipMethodID, @od; SET @i + = 1; END"

Pada satu server pengujian dengan jumlah total 8 inti fisik (16 logis), ini membutuhkan waktu 2 menit dan 5 detik. Pada server pengujian kedua dengan 24 inti fisik (48 logis), ini membutuhkan waktu 1 menit dan 0 detik.

Amati pemanfaatan CPU saat beban kerja berjalan, misalnya menggunakan task manager. Anda melihat bahwa pemanfaatan CPU mendekati 100%. Jika tidak demikian, Anda mengalami kemacetan I/O log, lihat juga Memecahkan masalah pengujian yang berjalan lambat.

Tabel berbasis disk

Perintah berikut menjalankan beban kerja pada tabel berbasis disk. Beban kerja ini mungkin memerlukan waktu lama untuk dieksekusi, yang sebagian besar disebabkan oleh kontensi kait dalam sistem. Tabel yang dioptimalkan memori bebas kait dan dengan demikian tidak menderita masalah ini.

Buka Prompt Cmd RML, dan jalankan perintah berikut:

Pilih tombol Salin untuk menyalin perintah, dan tempelkan ke prompt perintah Utilitas RML.

ostress.exe -n100 -r5000 -S. -E -dAdventureWorks2022 -q -Q"DECLARE @i AS INT = 0, @od AS Sales.SalesOrderDetailType_ondisk, @SalesOrderID AS INT, @DueDate AS DATETIME2 = sysdatetime(), @CustomerID AS INT = RAND() * 8000, @BillToAddressID AS INT = RAND() * 10000, @ShipToAddressID AS INT = RAND() * 10000, @ShipMethodID AS INT = (RAND() * 5) + 1; INSERT INTO @od SELECT OrderQty, ProductID, SpecialOfferID FROM Demo.DemoSalesOrderDetailSeed WHERE OrderID = CAST ((RAND() * 106) + 1 AS INT); WHILE (@i < 20) BEGIN EXECUTE Sales.usp_InsertSalesOrder_ondisk @SalesOrderID OUTPUT, @DueDate, @CustomerID, @BillToAddressID, @ShipToAddressID, @ShipMethodID, @od; SET @i + = 1; END"

Pada satu server pengujian dengan jumlah total 8 inti fisik (16 logis), ini membutuhkan waktu 41 menit dan 25 detik. Pada server pengujian kedua dengan 24 inti fisik (48 logis), ini membutuhkan waktu 52 menit dan 16 detik.

Faktor utama dalam perbedaan performa antara tabel yang dioptimalkan memori dan tabel berbasis disk dalam pengujian ini, adalah bahwa saat menggunakan tabel berbasis disk, SQL Server tidak dapat sepenuhnya menggunakan CPU. Alasannya adalah kekontensian kait: transaksi yang berjalan bersamaan mencoba menulis ke halaman data yang sama; kait digunakan untuk memastikan bahwa hanya satu transaksi yang dapat menulis ke halaman pada satu waktu. Mesin In-Memory OLTP bebas kait, dan baris data tidak diatur dalam halaman. Dengan demikian, transaksi yang berlangsung secara bersamaan tidak menghalangi penyisipan satu sama lain, sehingga memungkinkan SQL Server untuk memanfaatkan CPU secara optimal.

Anda dapat mengamati pemanfaatan CPU saat beban kerja berjalan, misalnya menggunakan task manager. Anda melihat dengan tabel berbasis disk, pemanfaatan CPU jauh dari 100%. Pada konfigurasi pengujian dengan 16 prosesor logis, pemanfaatan akan berkisar sekitar 24%.

Secara opsional, Anda dapat melihat jumlah tunggu kait per detik menggunakan Monitor Performa dengan penghitung kinerja \SQL Server:Latches\Latch Waits/sec.

Mengatur ulang demo

Untuk mengatur ulang demo, buka Perintah Cmd RML, dan jalankan perintah berikut:

ostress.exe -S. -E -dAdventureWorks2022 -Q"EXEC Demo.usp_DemoReset"

Bergantung pada perangkat keras, ini mungkin perlu waktu beberapa menit untuk dijalankan.

Kami merekomendasikan reset setelah setiap demo berjalan. Karena beban kerja ini hanya memasukkan, setiap kali dijalankan mengonsumsi lebih banyak memori, maka diperlukan reset untuk mencegah kehabisan memori. Jumlah memori yang digunakan setelah pekerjaan dijalankan dibahas dalam Bagian Pemanfaatan Memori setelah menjalankan beban kerja.

Memecahkan masalah pengujian yang berjalan lambat

Hasil pengujian biasanya bervariasi menurut perangkat keras, dan juga tingkat konkurensi yang digunakan dalam pelaksanaan pengujian. Beberapa hal yang perlu dicari jika hasilnya tidak seperti yang diharapkan:

  • Jumlah transaksi bersamaan: Saat menjalankan beban sistem pada satu utas, peningkatan kinerja dengan In-Memory OLTP kemungkinan kurang dari dua kali lipat. Ketidakcocokan kait hanya masalah yang signifikan jika ada tingkat konkurensi yang tinggi.

  • Jumlah inti yang tersedia rendah untuk SQL Server: Ini berarti ada tingkat konkurensi yang rendah dalam sistem, karena hanya ada transaksi yang dapat dijalankan secara bersamaan sebanyak inti yang tersedia untuk SQL.

    • Gejala: jika pemanfaatan CPU tinggi saat menjalankan beban kerja pada tabel berbasis disk, ini berarti tidak ada banyak ketidakcocokan, menunjuk ke kurangnya konkurensi.
  • Kecepatan drive log: Jika drive log tidak dapat mengikuti tingkat throughput transaksi dalam sistem, beban kerja menjadi tersempitan pada IO log. Meskipun pencatatan log lebih efisien dengan In-Memory OLTP, jika IO log menjadi hambatan, potensi peningkatan performa menjadi terbatas.

    • Gejala: jika pemanfaatan CPU tidak mendekati 100% atau sangat berfluktuasi saat menjalankan beban kerja pada tabel yang dioptimalkan memori, kemungkinan ada hambatan IO log. Ini dapat dikonfirmasi dengan membuka Resource Monitor dan melihat panjang antrean untuk drive log.

Pemanfaatan ruang memori dan disk dalam sampel

Dalam contoh berikut, kami menjelaskan apa yang diharapkan dalam hal pemanfaatan memori dan ruang disk untuk database sampel. Kami juga menunjukkan hasil dari pada server pengujian dengan 16 inti logis.

Pemanfaatan memori untuk tabel yang dioptimalkan memori

Pemanfaatan database secara keseluruhan

Kueri berikut dapat digunakan untuk mendapatkan total pemanfaatan memori untuk In-Memory OLTP dalam sistem.

SELECT type,
       name,
       pages_kb / 1024 AS pages_MB
FROM sys.dm_os_memory_clerks
WHERE type LIKE '%xtp%';

Rekam jepret setelah database baru saja dibuat:

jenis nama halaman_MB
MEMORYCLERK_XTP Bawaan 94
MEMORYCLERK_XTP DB_ID_5 877
MEMORYCLERK_XTP Bawaan 0
MEMORYCLERK_XTP Bawaan 0

Penjaga memori default berisi struktur memori yang berlaku untuk seluruh sistem dan berukuran relatif kecil. Pengelola memori untuk database pengguna, dalam hal ini, database dengan ID 5 (database_id mungkin berbeda dalam instance Anda), adalah sekitar 900 MB.

Pemanfaatan memori per tabel

Kueri berikut dapat digunakan untuk menelusuri paling detail pemanfaatan memori tabel individual dan indeksnya:

SELECT object_name(t.object_id) AS [Table name],
       memory_allocated_for_table_kb,
       memory_allocated_for_indexes_kb
FROM sys.dm_db_xtp_table_memory_stats AS dms
     INNER JOIN sys.tables AS t
         ON dms.object_id = t.object_id
WHERE t.type = 'U';

Tabel berikut ini menampilkan hasil kueri ini untuk penginstalan sampel baru:

Nama tabel memory_allocated_for_table_kb memory_allocated_for_indexes_kb
SpecialOfferProduct_inmem 64 3840
DemoSalesOrderHeaderSeed 1984 5504
SalesOrderDetail_inmem 15316 663552
DemoSalesOrderDetailSeed 64 10432
SpecialOffer_inmem 3 8192
SalesOrderHeader_inmem 7168 147456
Product_inmem 124 12352

Seperti yang Anda lihat, tabelnya cukup kecil: SalesOrderHeader_inmem sekitar 7 MB, dan SalesOrderDetail_inmem berukuran sekitar 15 MB.

Apa yang mencolok di sini adalah ukuran memori yang dialokasikan untuk indeks, dibandingkan dengan ukuran data tabel. Itu karena indeks hash dalam sampel telah ditentukan sebelumnya untuk ukuran data yang lebih besar. Indeks hash memiliki ukuran tetap, dan dengan demikian ukurannya tidak tumbuh dengan ukuran data dalam tabel.

Pemanfaatan memori setelah menjalankan beban kerja

Setelah memasukkan 10 juta pesanan penjualan, pemanfaatan total memori terlihat mirip dengan kueri berikut:

SELECT type,
       name,
       pages_kb / 1024 AS pages_MB
FROM sys.dm_os_memory_clerks
WHERE type LIKE '%xtp%';

Berikut kumpulan hasilnya.

type name pages_MB
MEMORYCLERK_XTP Bawaan 146
MEMORYCLERK_XTP DB_ID_5 7374
MEMORYCLERK_XTP Bawaan 0
MEMORYCLERK_XTP Bawaan 0

Seperti yang Anda lihat, SQL Server menggunakan sedikit di bawah 8 GB untuk tabel dan indeks yang dioptimalkan memori dalam database sampel.

Melihat penggunaan memori terperinci per tabel setelah satu contoh dijalankan:

SELECT object_name(t.object_id) AS [Table name],
       memory_allocated_for_table_kb,
       memory_allocated_for_indexes_kb
FROM sys.dm_db_xtp_table_memory_stats AS dms
     INNER JOIN sys.tables AS t
         ON dms.object_id = t.object_id
WHERE t.type = 'U';

Berikut kumpulan hasilnya.

Table name memory_allocated_for_table_kb memory_allocated_for_indexes_kb
SalesOrderDetail_inmem 5113761 663552
DemoSalesOrderDetailSeed 64 10368
SpecialOffer_inmem 2 8192
SalesOrderHeader_inmem 1575679 147456
Product_inmem 111 12032
ProdukPenawaranKhusus_inmem 64 3712
DemoSalesOrderHeaderSeed 1984 5504

Kita dapat melihat total sekitar 6,5 GB data. Ukuran indeks pada tabel SalesOrderHeader_inmem dan SalesOrderDetail_inmem sama dengan ukuran indeks sebelum menyisipkan pesanan penjualan. Ukuran indeks tidak berubah karena kedua tabel menggunakan indeks hash, dan indeks hash statis.

Setelah demo diatur ulang

Prosedur Demo.usp_DemoReset tersimpan dapat digunakan untuk mengatur ulang demo. Ini menghapus data dalam tabel SalesOrderHeader_inmem dan SalesOrderDetail_inmem, dan mengisi ulang data dari tabel asli SalesOrderHeader dan SalesOrderDetail.

Sekarang, meskipun baris dalam tabel dihapus, ini tidak berarti bahwa memori segera diklaim kembali. SQL Server mengklaim kembali memori dari baris yang dihapus dalam tabel yang dioptimalkan memori di latar belakang, sesuai kebutuhan. Anda melihat bahwa segera setelah reset demo, tanpa beban kerja transaksional pada sistem, memori dari baris yang dihapus belum diklaim kembali:

SELECT type,
       name,
       pages_kb / 1024 AS pages_MB
FROM sys.dm_os_memory_clerks
WHERE type LIKE '%xtp%';

Berikut kumpulan hasilnya.

type name pages_MB
MEMORYCLERK_XTP Bawaan 2261
MEMORYCLERK_XTP DB_ID_5 7396
MEMORYCLERK_XTP Bawaan 0
MEMORYCLERK_XTP Bawaan 0

Hal ini diharapkan: memori dipulihkan ketika beban kerja transaksi berjalan.

Jika Anda memulai eksekusi kedua beban kerja demo, Anda akan melihat pemanfaatan memori berkurang pada awalnya, karena baris yang dihapus sebelumnya dibersihkan. Pada titik tertentu, ukuran memori meningkat lagi sampai beban kerja selesai. Setelah memasukkan 10 juta baris setelah reset demo, pemanfaatan memori sangat mirip dengan pemanfaatan setelah eksekusi pertama. Contohnya:

SELECT type,
       name,
       pages_kb / 1024 AS pages_MB
FROM sys.dm_os_memory_clerks
WHERE type LIKE '%xtp%';

Berikut kumpulan hasilnya.

type name pages_MB
MEMORYCLERK_XTP Bawaan 1863
MEMORYCLERK_XTP DB_ID_5 7390
MEMORYCLERK_XTP Bawaan 0
MEMORYCLERK_XTP Bawaan 0

Pemanfaatan disk untuk tabel yang dioptimalkan untuk memori

Ukuran on-disk secara keseluruhan untuk file titik pemeriksaan database pada waktu tertentu dapat ditemukan menggunakan kueri:

SELECT SUM(df.size) * 8 / 1024 AS [On-disk size in MB]
FROM sys.filegroups AS f
     INNER JOIN sys.database_files AS df
         ON f.data_space_id = df.data_space_id
WHERE f.type = N'FX';

Status awal

Ketika grup file sampel dan sampel tabel yang dioptimalkan memori dibuat pada awalnya, beberapa file titik pemeriksaan dibuat sebelumnya dan sistem mulai mengisi file - jumlah file titik pemeriksaan yang dibuat sebelumnya tergantung pada jumlah prosesor logis dalam sistem. Karena sampel awalnya sangat kecil, file yang dibuat sebelumnya sebagian besar kosong setelah pembuatan awal.

Kode berikut menunjukkan ukuran awal pada disk untuk sampel pada komputer dengan 16 prosesor logis:

SELECT SUM(df.size) * 8 / 1024 AS [On-disk size in MB]
FROM sys.filegroups AS f
     INNER JOIN sys.database_files AS df
         ON f.data_space_id = df.data_space_id
WHERE f.type = N'FX';

Berikut kumpulan hasilnya.

Ukuran pada disk dalam MB
2312

Seperti yang Anda lihat, ada perbedaan besar antara ukuran pada disk file titik pemeriksaan, yaitu 2,3 GB, dan ukuran data aktual, yang lebih dekat ke 30 MB.

Menelusuri lebih dalam tentang dari mana asal pemanfaatan ruang disk, Anda bisa menggunakan kueri berikut. Ukuran pada disk yang dikembalikan oleh kueri ini adalah perkiraan untuk file dengan status dalam 5 (DIPERLUKAN UNTUK BACKUP/HA), 6 (DALAM TRANSISI KE TOMBSTONE), atau 7 (TOMBSTONE).

SELECT state_desc,
       file_type_desc,
       COUNT(*) AS [count],
       SUM(CASE WHEN state = 5 AND file_type = 0 THEN 128 * 1024 * 1024
                WHEN state = 5 AND file_type = 1 THEN 8 * 1024 * 1024
                WHEN state IN (6, 7) THEN 68 * 1024 * 1024
           ELSE file_size_in_bytes END) / 1024 / 1024 AS [on-disk size MB]
FROM sys.dm_db_xtp_checkpoint_files
GROUP BY state, state_desc, file_type, file_type_desc
ORDER BY state, file_type;

Untuk status awal sampel, hasilnya terlihat seperti tabel berikut untuk server dengan 16 prosesor logis:

state_desc deskripsi_tipe_berkas jumlah ukuran pada disk MB
DIBUAT SEBELUMNYA DATA 16 2048
DIBUAT SEBELUMNYA DELTA 16 128
SEDANG DIBANGUN DATA 1 128
SEDANG DIBANGUN DELTA 1 8

Seperti yang Anda lihat, sebagian besar ruang digunakan oleh data dan file delta yang dibuat sebelumnya. SQL Server telah lebih dulu membuat satu pasang file (data, delta) untuk setiap prosesor logis. Selain itu, file data dipertahankan pada 128 MB, dan file delta pada 8 MB, untuk membuat penyisipan data ke dalam file-file ini lebih efisien.

Data aktual dalam tabel yang dioptimalkan memori ada dalam satu file data.

Setelah menjalankan beban kerja

Setelah satu kali uji coba yang menyisipkan 10 juta pesanan penjualan, ukuran keseluruhan pada disk terlihat seperti ini (untuk server pengujian 16-core):

SELECT SUM(df.size) * 8 / 1024 AS [On-disk size in MB]
FROM sys.filegroups AS f
     INNER JOIN sys.database_files AS df
         ON f.data_space_id = df.data_space_id
WHERE f.type = N'FX';

Berikut kumpulan hasilnya.

Ukuran pada disk dalam MB
8828

Ukuran pada disk mendekati 9 GB, yang mendekati ukuran dalam memori data.

Melihat lebih dekat ukuran file titik pemeriksaan di berbagai status:

SELECT state_desc,
       file_type_desc,
       COUNT(*) AS [count],
       SUM(CASE WHEN state = 5 AND file_type = 0 THEN 128 * 1024 * 1024
                WHEN state = 5 AND file_type = 1 THEN 8 * 1024 * 1024
                WHEN state IN (6, 7) THEN 68 * 1024 * 1024
            ELSE file_size_in_bytes END) / 1024 / 1024 AS [on-disk size MB]
FROM sys.dm_db_xtp_checkpoint_files
GROUP BY state, state_desc, file_type, file_type_desc
ORDER BY state, file_type;

Berikut kumpulan hasilnya.

state_desc file_type_desc count on-disk size MB
DIBUAT SEBELUMNYA DATA 16 2048
DIBUAT SEBELUMNYA DELTA 16 128
SEDANG DIBANGUN DATA 1 128
SEDANG DIBANGUN DELTA 1 8

Kami masih memiliki 16 pasang file pra-dibuat, siap untuk digunakan saat titik pemeriksaan ditutup.

Ada satu pasang yang sedang dalam tahap pembangunan, yang digunakan hingga cek poin saat ini ditutup. Seiring dengan file titik pemeriksaan aktif, ini memberikan sekitar 6,5 GB pemanfaatan disk untuk 6,5 GB data dalam memori. Ingat bahwa indeks tidak bertahan pada disk, dan dengan demikian ukuran keseluruhan pada disk lebih kecil dari ukuran dalam memori dalam kasus ini.

Setelah demo diatur ulang

Setelah reset demo, ruang disk tidak segera diklaim kembali jika tidak ada beban kerja transaksional pada sistem, dan tidak ada titik pemeriksaan database. Agar file titik pemeriksaan dipindahkan melalui berbagai tahap mereka dan akhirnya dibuang, beberapa titik pemeriksaan dan peristiwa pemotongan log perlu terjadi, untuk memulai penggabungan file titik pemeriksaan, serta untuk memulai pengumpulan sampah. Ini terjadi secara otomatis jika Anda memiliki beban kerja transaksional dalam sistem (dan mengambil cadangan log reguler, jika Anda menggunakan model pemulihan PENUH), tetapi tidak ketika sistem menganggur, seperti dalam skenario demo.

Dalam contoh, setelah reset demo, Anda mungkin melihat sesuatu seperti:

SELECT SUM(df.size) * 8 / 1024 AS [On-disk size in MB]
FROM sys.filegroups AS f
     INNER JOIN sys.database_files AS df
         ON f.data_space_id = df.data_space_id
WHERE f.type = N'FX';

Berikut kumpulan hasilnya.

Ukuran pada disk dalam MB
11839

Pada hampir 12 GB, ini secara signifikan lebih dari 9 GB yang kami miliki sebelum reset demo. Ini karena beberapa penggabungan file titik pemeriksaan dimulai, tetapi beberapa target penggabungan belum diinstal, dan beberapa file sumber gabungan belum dibersihkan, seperti yang dapat dilihat dari contoh berikut:

SELECT state_desc,
       file_type_desc,
       COUNT(*) AS [count],
       SUM(CASE WHEN state = 5 AND file_type = 0 THEN 128 * 1024 * 1024
                WHEN state = 5 AND file_type = 1 THEN 8 * 1024 * 1024
                WHEN state IN (6, 7) THEN 68 * 1024 * 1024
           ELSE file_size_in_bytes END) / 1024 / 1024 AS [on-disk size MB]
FROM sys.dm_db_xtp_checkpoint_files
GROUP BY state, state_desc, file_type, file_type_desc
ORDER BY state, file_type;

Berikut kumpulan hasilnya.

state_desc file_type_desc count on-disk size MB
DIBUAT SEBELUMNYA DATA 16 2048
DIBUAT SEBELUMNYA DELTA 16 128
AKTIF DATA 38 5152
AKTIF DELTA 38 1331
GABUNGKAN SASARAN DATA 7 896
GABUNGKAN SASARAN DELTA 7 56
SUMBER GABUNGAN DATA 13 1772
SUMBER GABUNGAN DELTA 13 455

Target penggabungan diinstal dan sumber gabungan dibersihkan saat aktivitas transaksi terjadi dalam sistem.

Setelah menjalankan beban kerja demo kedua, memasukkan 10 juta pesanan penjualan setelah reset demo, Anda melihat bahwa file yang dibangun selama eksekusi pertama beban kerja dibersihkan. Jika Anda menjalankan kueri sebelumnya beberapa kali saat beban kerja berjalan, Anda dapat melihat file titik pemeriksaan melewati berbagai tahap.

Setelah memasukkan 10 juta pesanan penjualan dalam eksekusi kedua beban kerja, Anda akan melihat bahwa pemanfaatan disk sangat mirip dengan, meskipun belum tentu sama seperti setelah eksekusi pertama, karena sistem bersifat dinamis. Contohnya:

SELECT state_desc,
       file_type_desc,
       COUNT(*) AS [count],
       SUM(CASE WHEN state = 5 AND file_type = 0 THEN 128 * 1024 * 1024
                WHEN state = 5 AND file_type = 1 THEN 8 * 1024 * 1024
                WHEN state IN (6, 7) THEN 68 * 1024 * 1024
           ELSE file_size_in_bytes END) / 1024 / 1024 AS [on-disk size MB]
FROM sys.dm_db_xtp_checkpoint_files
GROUP BY state, state_desc, file_type, file_type_desc
ORDER BY state, file_type;

Berikut kumpulan hasilnya.

state_desc file_type_desc count on-disk size MB
DIBUAT SEBELUMNYA DATA 16 2048
DIBUAT SEBELUMNYA DELTA 16 128
SEDANG DIBANGUN DATA 2 268
SEDANG DIBANGUN DELTA 2 16
AKTIF DATA 41 5608
AKTIF DELTA 41 328

Dalam hal ini, ada dua pasangan file checkpoint dalam UNDER CONSTRUCTION status, yang mengindikasikan bahwa beberapa pasangan file dipindahkan ke UNDER CONSTRUCTION status, kemungkinan karena tingkat konkurensi yang tinggi dalam beban kerja. Beberapa utas bersamaan memerlukan pasangan file baru secara bersamaan, dan dengan demikian memindahkan pasangan dari PRECREATED ke UNDER CONSTRUCTION.