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

Ketik dengan Kuat Parameter Bernilai Tabel itu

Parameter bernilai tabel telah ada sejak SQL Server 2008 dan menyediakan mekanisme yang berguna untuk mengirim beberapa baris data ke SQL Server, disatukan sebagai panggilan berparameter tunggal. Setiap baris kemudian tersedia dalam variabel tabel yang kemudian dapat digunakan dalam pengkodean T-SQL standar, yang menghilangkan kebutuhan untuk menulis logika pemrosesan khusus untuk memecah data lagi. Menurut definisinya, parameter bernilai tabel diketik dengan kuat ke tipe tabel yang ditentukan pengguna yang harus ada di dalam database tempat panggilan dilakukan. Namun, sangat diketik tidak benar-benar "sangat diketik" seperti yang Anda harapkan, karena artikel ini akan menunjukkan, dan kinerja dapat terpengaruh sebagai hasilnya.

Untuk mendemonstrasikan potensi dampak kinerja dari salah ketik parameter bernilai tabel dengan SQL Server, kita akan membuat contoh tipe tabel yang ditentukan pengguna dengan struktur berikut:

CREATE TYPE dbo.PharmacyData AS TABLE
(
  Dosage        int,
  Drug          varchar(20),
  FirstName     varchar(50),
  LastName      varchar(50),
  AddressLine1  varchar(250),
  PhoneNumber   varchar(50),
  CellNumber    varchar(50),
  EmailAddress  varchar(100),
  FillDate      datetime
);

Kemudian kita akan membutuhkan aplikasi .NET yang akan menggunakan tipe tabel yang ditentukan pengguna ini sebagai parameter input untuk meneruskan data ke SQL Server. Untuk menggunakan parameter bernilai tabel dari aplikasi kita, objek DataTable biasanya diisi dan kemudian diteruskan sebagai nilai untuk parameter dengan tipe SqlDbType.Structured. DataTable dapat dibuat dengan berbagai cara dalam kode .NET, tetapi cara umum untuk membuat tabel adalah seperti berikut:

System.Data.DataTable DefaultTable = new System.Data.DataTable("@PharmacyData");
DefaultTable.Columns.Add("Dosage",       typeof(int));
DefaultTable.Columns.Add("Drug",         typeof(string));
DefaultTable.Columns.Add("FirstName",    typeof(string));
DefaultTable.Columns.Add("LastName",     typeof(string));
DefaultTable.Columns.Add("AddressLine1", typeof(string));
DefaultTable.Columns.Add("PhoneNumber",  typeof(string));
DefaultTable.Columns.Add("CellNumber",   typeof(string));
DefaultTable.Columns.Add("EmailAddress", typeof(string));
DefaultTable.Columns.Add("Date",         typeof(DateTime));

Anda juga dapat membuat DataTable menggunakan definisi inline sebagai berikut:

System.Data.DataTable DefaultTable = new System.Data.DataTable("@PharmacyData")
{
  Columns =
  {
    {"Dosage",       typeof(int)},
    {"Drug",         typeof(string)},
    {"FirstName",    typeof(string)},
    {"LastName",     typeof(string)},
    {"AddressLine1", typeof(string)},
    {"PhoneNumber",  typeof(string)},
    {"CellNumber",   typeof(string)},
    {"EmailAddress", typeof(string)},
    {"Date",         typeof(DateTime)},
  },
  Locale = CultureInfo.InvariantCulture
};

Salah satu dari definisi objek DataTable ini di .NET dapat digunakan sebagai parameter bernilai tabel untuk tipe data yang ditentukan pengguna yang dibuat, tetapi perhatikan definisi tipe(string) untuk berbagai kolom string; ini semua mungkin diketik dengan "benar" tetapi sebenarnya tidak diketik dengan kuat untuk tipe data yang diterapkan dalam tipe data yang ditentukan pengguna. Kita dapat mengisi tabel dengan data acak dan meneruskannya ke SQL Server sebagai parameter ke pernyataan SELECT yang sangat sederhana yang akan mengembalikan baris yang sama persis dengan tabel yang kita lewati, sebagai berikut:

using (SqlCommand cmd = new SqlCommand("SELECT * FROM @tvp;", connection))
{
  var pList = new SqlParameter("@tvp", SqlDbType.Structured);
  pList.TypeName = "dbo.PharmacyData";
  pList.Value = DefaultTable;
  cmd.Parameters.Add(pList);
  cmd.ExecuteReader().Dispose();
}

Kami kemudian dapat menggunakan jeda debug sehingga kami dapat memeriksa definisi DefaultTable selama eksekusi, seperti yang ditunjukkan di bawah ini:

Kita dapat melihat bahwa MaxLength untuk kolom string diatur pada -1, yang berarti mereka sedang melewati TDS ke SQL Server sebagai LOB (Objek Besar) atau pada dasarnya sebagai kolom bertipe data MAX, dan ini dapat memengaruhi kinerja secara negatif. Jika kita mengubah definisi .NET DataTable menjadi sangat diketik ke definisi skema tipe tabel yang ditentukan pengguna sebagai berikut dan melihat MaxLength dari kolom yang sama menggunakan jeda debug:

System.Data.DataTable SchemaTable = new System.Data.DataTable("@PharmacyData")
{
  Columns =
  {
    {new DataColumn() { ColumnName = "Dosage",        DataType = typeof(int)} },
    {new DataColumn() { ColumnName = "Drug",          DataType = typeof(string), MaxLength = 20} },
    {new DataColumn() { ColumnName = "FirstName",     DataType = typeof(string), MaxLength = 50} },
    {new DataColumn() { ColumnName = "LastName",      DataType = typeof(string), MaxLength = 50} },
    {new DataColumn() { ColumnName = "AddressLine1",  DataType = typeof(string), MaxLength = 250} },
    {new DataColumn() { ColumnName = "PhoneNumber",   DataType = typeof(string), MaxLength = 50} },
    {new DataColumn() { ColumnName = "CellNumber",    DataType = typeof(string), MaxLength = 50} },
    {new DataColumn() { ColumnName = "EmailAddress",  DataType = typeof(string), MaxLength = 100} },
    {new DataColumn() { ColumnName = "Date",          DataType = typeof(DateTime)} },
  },
  Locale = CultureInfo.InvariantCulture
};

Kami sekarang memiliki panjang yang benar untuk definisi kolom, dan kami tidak akan meneruskannya sebagai LOB melalui TDS ke SQL Server.

Bagaimana ini memengaruhi kinerja, Anda mungkin bertanya-tanya? Ini memengaruhi jumlah buffer TDS yang dikirim melalui jaringan ke SQL Server, dan juga memengaruhi waktu pemrosesan keseluruhan untuk perintah.

Menggunakan kumpulan data yang sama persis untuk dua tabel data, dan memanfaatkan metode RetrieveStatistics pada objek SqlConnection memungkinkan kita mendapatkan metrik statistik ExecutionTime dan BuffersSent untuk panggilan ke perintah SELECT yang sama, dan hanya menggunakan dua definisi DataTable yang berbeda sebagai parameter dan memanggil metode ResetStatistics objek SqlConnection memungkinkan statistik eksekusi dihapus di antara pengujian.

Definisi GetSchemaTable menentukan MaxLength untuk setiap kolom string dengan benar di mana GetTable hanya menambahkan kolom tipe string yang memiliki nilai MaxLength diatur ke -1 menghasilkan 100 buffer TDS tambahan yang dikirim untuk 861 baris data dalam tabel dan runtime 158 milidetik dibandingkan dengan hanya 250 buffer yang dikirim untuk definisi DataTable yang diketik dengan kuat dan waktu proses 111 milidetik. Meskipun ini mungkin tidak tampak seperti banyak dalam skema besar, ini adalah panggilan tunggal, eksekusi tunggal, dan akumulasi dampak dari waktu ke waktu selama ribuan atau jutaan eksekusi tersebut adalah di mana manfaat mulai bertambah dan memiliki dampak yang nyata. pada kinerja beban kerja dan throughput.

Di mana ini benar-benar dapat membuat perbedaan adalah dalam implementasi cloud di mana Anda membayar lebih dari sekadar sumber daya komputasi dan penyimpanan. Selain memiliki biaya tetap sumber daya perangkat keras untuk Azure VM, SQL Database, atau AWS EC2 atau RDS, ada biaya tambahan untuk lalu lintas jaringan ke dan dari cloud yang ditempelkan ke penagihan untuk setiap bulan. Mengurangi buffer yang melintasi kabel akan menurunkan TCO untuk solusi dari waktu ke waktu, dan perubahan kode yang diperlukan untuk menerapkan penghematan ini relatif sederhana.


  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 CREATE TABLE untuk Pemula

  2. bagaimana cara Menjalankan Prosedur Tersimpan di SQL Developer?

  3. Cara Mengklasifikasikan, Menemukan, dan Menyamarkan PII di Basis Data…

  4. Menghubungkan ke Lotus Notes dari Java

  5. Berapa Banyak RAM yang Dibutuhkan Server Database Baru Anda?