Beberapa contoh untuk ditampilkan, cukup dimetikan:
Inline Table Valued
CREATE FUNCTION MyNS.GetUnshippedOrders()
RETURNS TABLE
AS
RETURN SELECT a.SaleId, a.CustomerID, b.Qty
FROM Sales.Sales a INNER JOIN Sales.SaleDetail b
ON a.SaleId = b.SaleId
INNER JOIN Production.Product c ON b.ProductID = c.ProductID
WHERE a.ShipDate IS NULL
GO
Multi Statement Table Dinilai
CREATE FUNCTION MyNS.GetLastShipped(@CustomerID INT)
RETURNS @CustomerOrder TABLE
(SaleOrderID INT NOT NULL,
CustomerID INT NOT NULL,
OrderDate DATETIME NOT NULL,
OrderQty INT NOT NULL)
AS
BEGIN
DECLARE @MaxDate DATETIME
SELECT @MaxDate = MAX(OrderDate)
FROM Sales.SalesOrderHeader
WHERE CustomerID = @CustomerID
INSERT @CustomerOrder
SELECT a.SalesOrderID, a.CustomerID, a.OrderDate, b.OrderQty
FROM Sales.SalesOrderHeader a INNER JOIN Sales.SalesOrderHeader b
ON a.SalesOrderID = b.SalesOrderID
INNER JOIN Production.Product c ON b.ProductID = c.ProductID
WHERE a.OrderDate = @MaxDate
AND a.CustomerID = @CustomerID
RETURN
END
GO
Apakah ada keuntungan menggunakan satu jenis (in-line atau multi pernyataan) daripada yang lain? Adakah skenario tertentu ketika yang satu lebih baik dari yang lain atau apakah perbedaannya murni sintaksis? Saya menyadari dua contoh pertanyaan melakukan hal yang berbeda tetapi apakah ada alasan saya akan menulisnya dengan cara itu?
Membaca tentang mereka dan kelebihan / perbedaan belum benar-benar dijelaskan.
Jawaban:
Dalam meneliti komentar Matt, saya telah merevisi pernyataan asli saya. Dia benar, akan ada perbedaan kinerja antara fungsi nilai tabel inline (ITVF) dan fungsi nilai tabel multi-pernyataan (MSTVF) bahkan jika mereka berdua hanya menjalankan pernyataan SELECT. SQL Server akan memperlakukan ITVF seperti
VIEW
karena akan menghitung rencana eksekusi menggunakan statistik terbaru pada tabel yang dimaksud. MSTVF setara dengan menjejalkan seluruh isi pernyataan SELECT Anda ke dalam variabel tabel dan kemudian bergabung dengannya. Dengan demikian, kompilator tidak dapat menggunakan statistik tabel apa pun pada tabel di MSTVF. Jadi, semua hal dianggap sama, (yang jarang terjadi), ITVF akan tampil lebih baik daripada MSTVF. Dalam pengujian saya, perbedaan kinerja dalam waktu penyelesaian dapat diabaikan namun dari sudut pandang statistik, itu terlihat.Dalam kasus Anda, kedua fungsi tersebut tidak setara secara fungsional. Fungsi MSTV melakukan kueri tambahan setiap kali dipanggil dan, yang paling penting, filter pada id pelanggan. Dalam kueri besar, pengoptimal tidak akan dapat mengambil keuntungan dari gabungan jenis lain karena akan perlu memanggil fungsi untuk setiap pelanggan yang dilewati. Namun, jika Anda menulis ulang fungsi MSTV Anda seperti ini:
Dalam kueri, pengoptimal akan dapat memanggil fungsi itu sekali dan membangun rencana eksekusi yang lebih baik tetapi tetap tidak akan lebih baik daripada ITVS yang setara, non-parameterisasi atau a
VIEW
.ITVFs harus lebih disukai daripada MSTVFs jika memungkinkan karena tipe data, nullability dan collation dari kolom dalam tabel sedangkan Anda mendeklarasikan properti-properti tersebut dalam fungsi bernilai tabel multi-pernyataan dan, yang penting, Anda akan mendapatkan rencana eksekusi yang lebih baik dari ITVF. Dalam pengalaman saya, saya belum menemukan banyak keadaan di mana ITVF adalah pilihan yang lebih baik daripada VIEW tetapi jarak tempuh dapat bervariasi.
Terima kasih untuk Matt.
Tambahan
Karena saya melihat ini muncul baru-baru ini, berikut adalah analisis yang sangat baik yang dilakukan oleh Wayne Sheffield membandingkan perbedaan kinerja antara fungsi Inline Table Valued dan fungsi Multi-Statement.
Posting blog aslinya.
Salin di SQL Server Central
sumber
Secara internal, SQL Server memperlakukan fungsi bernilai tabel inline seperti itu akan melihat dan memperlakukan fungsi multi-pernyataan tabel dihargai mirip dengan bagaimana itu akan prosedur yang tersimpan.
Ketika fungsi tabel bernilai inline digunakan sebagai bagian dari kueri luar, prosesor kueri memperluas definisi UDF dan menghasilkan rencana eksekusi yang mengakses objek yang mendasarinya, menggunakan indeks pada objek ini.
Untuk fungsi bernilai multi-pernyataan tabel, rencana eksekusi dibuat untuk fungsi itu sendiri dan disimpan dalam cache rencana eksekusi (setelah fungsi dijalankan pertama kali). Jika fungsi multi-pernyataan tabel bernilai digunakan sebagai bagian dari kueri yang lebih besar maka pengoptimal tidak tahu apa fungsi kembali, dan membuat beberapa asumsi standar - yang pada dasarnya mengasumsikan bahwa fungsi akan mengembalikan satu baris, dan bahwa pengembalian dari fungsi akan diakses dengan menggunakan pemindaian tabel terhadap tabel dengan satu baris.
Di mana fungsi multi-pernyataan tabel bernilai bisa berkinerja buruk adalah ketika mereka mengembalikan sejumlah besar baris dan bergabung melawan dalam kueri luar. Masalah kinerja terutama karena fakta bahwa pengoptimal akan menghasilkan rencana dengan asumsi bahwa satu baris dikembalikan, yang tidak harus menjadi rencana yang paling tepat.
Sebagai aturan umum, kami telah menemukan bahwa jika mungkin, fungsi inline table bernilai harus digunakan sebagai preferensi terhadap yang multi-pernyataan (ketika UDF akan digunakan sebagai bagian dari kueri luar) karena potensi masalah kinerja ini.
sumber
Ada perbedaan lain. Fungsi bernilai tabel inline dapat dimasukkan ke dalam, diperbarui, dan dihapus dari - seperti halnya tampilan. Pembatasan serupa berlaku - tidak dapat memperbarui fungsi menggunakan agregat, tidak dapat memperbarui kolom terhitung, dan sebagainya.
sumber
Contoh Anda, saya pikir, menjawab pertanyaan dengan sangat baik. Fungsi pertama dapat dilakukan sebagai pilihan tunggal, dan merupakan alasan yang baik untuk menggunakan gaya inline. Yang kedua mungkin dapat dilakukan sebagai pernyataan tunggal (menggunakan sub-kueri untuk mendapatkan tanggal maksimum), tetapi beberapa coders mungkin merasa lebih mudah dibaca atau lebih alami untuk melakukannya dalam banyak pernyataan seperti yang telah Anda lakukan. Beberapa fungsi yang tidak bisa dilakukan dalam satu pernyataan, dan karenanya membutuhkan versi multi-pernyataan.
Saya sarankan menggunakan yang paling sederhana (sebaris) bila memungkinkan, dan menggunakan multi-pernyataan bila perlu (jelas) atau ketika preferensi pribadi / keterbacaan membuatnya dengan mengetik ekstra.
sumber
lihat Fungsi Membandingkan Inline dan Multi-Statement Table-Valued Anda dapat menemukan deskripsi yang baik dan tolok ukur kinerja
sumber
Saya belum menguji ini, tetapi fungsi pernyataan multi-cache hasil set. Mungkin ada kasus di mana ada terlalu banyak pengoptimal untuk menjalankan fungsi. Misalnya, Anda memiliki fungsi yang mengembalikan hasil dari database berbeda tergantung pada apa yang Anda lewati sebagai "Nomor Perusahaan". Biasanya, Anda bisa membuat tampilan dengan gabungan semua kemudian disaring berdasarkan nomor perusahaan tapi saya menemukan bahwa kadang-kadang server sql menarik kembali seluruh serikat dan tidak cukup pintar untuk memanggil satu pilih. Fungsi tabel dapat memiliki logika untuk memilih sumber.
sumber
Kasus lain untuk menggunakan fungsi multi-line adalah untuk menghindari sql server menekan klausa where.
Sebagai contoh, saya memiliki tabel dengan nama tabel dan beberapa nama tabel diformat seperti C05_2019 dan C12_2018 dan dan semua tabel yang diformat seperti itu memiliki skema yang sama. Saya ingin menggabungkan semua data itu menjadi satu tabel dan menguraikan 05 dan 12 ke kolom CompNo dan 2018.2019 ke dalam kolom tahun. Namun, ada tabel lain seperti ACA_StupidTable yang saya tidak dapat mengekstrak CompNo dan CompYr dan akan mendapatkan kesalahan konversi jika saya mencoba. Jadi, kueri saya ada di dua bagian, kueri dalam yang mengembalikan hanya tabel yang diformat seperti 'C_______' kemudian kueri luar melakukan konversi sub-string dan int. yaitu Cast (Substring (2, 2) sebagai int) sebagai CompNo. Semua terlihat bagus kecuali bahwa sql server memutuskan untuk meletakkan fungsi Cast saya sebelum hasilnya difilter dan jadi saya mendapatkan kesalahan konversi pikiran. Fungsi tabel multi pernyataan dapat mencegah hal itu terjadi,
sumber
Mungkin dengan cara yang sangat kental. ITVF (inline TVF): lebih jika Anda adalah orang DB, adalah jenis tampilan parameter, ambil satu SELECT st
MTVF (Multi-statement TVF): Pengembang, membuat dan memuat variabel tabel.
sumber
jika Anda akan melakukan kueri, Anda dapat bergabung dalam fungsi Nilai Tabel Inline Anda seperti:
itu akan menimbulkan sedikit overhead dan berjalan dengan baik.
jika Anda mencoba menggunakan Tabel Multi Pernyataan yang Dinilai dalam kueri serupa, Anda akan memiliki masalah kinerja:
karena Anda akan menjalankan fungsi 1 kali untuk setiap baris yang dikembalikan, karena hasil yang ditetapkan menjadi besar, itu akan berjalan lebih lambat dan lebih lambat.
sumber