Saat membuat profil basis data, saya menemukan tampilan yang merujuk beberapa fungsi non-deterministik yang dapat diakses 1000-2500 kali per menit untuk setiap koneksi dalam kumpulan aplikasi ini. Sederhana SELECT
dari tampilan menghasilkan rencana eksekusi berikut:
Itu tampak seperti rencana rumit untuk tampilan yang memiliki kurang dari seribu baris yang dapat melihat satu atau dua baris berubah setiap beberapa bulan. Tapi itu menjadi lebih buruk dengan ketaatan lain berikut:
- Tampilan bersarang adalah non-deterministik, jadi kami tidak dapat mengindeksnya
- Setiap tampilan merujuk beberapa
UDF
s untuk membangun string - Setiap UDF berisi
UDF
s bersarang untuk mendapatkan kode ISO untuk bahasa lokal - Tampilan di tumpukan menggunakan pembangun string tambahan yang dikembalikan dari
UDF
s sebagaiJOIN
predikat - Setiap tumpukan tampilan diperlakukan sebagai tabel, artinya ada
INSERT
/UPDATE
/DELETE
pemicu pada masing-masing untuk menulis ke tabel yang mendasarinya - Pemicu ini pada pandangan menggunakan
CURSORS
yangEXEC
disimpan prosedur yang referensi lebih dari ini tali bangunanUDF
s.
Ini tampaknya sangat busuk bagi saya, tetapi saya hanya memiliki beberapa tahun pengalaman dengan TSQL. Menjadi lebih baik juga!
Tampaknya pengembang yang memutuskan bahwa ini adalah ide yang hebat, melakukan semua ini sehingga beberapa ratus string yang disimpan dapat memiliki terjemahan berdasarkan string yang dikembalikan dari UDF
yang khusus skema.
Inilah salah satu tampilan di tumpukan, tetapi semuanya sama-sama buruk:
CREATE VIEW [UserWKStringI18N]
AS
SELECT b.WKType, b.WKIndex
, CASE
WHEN ISNULL(il.I18NID, N'') = N''
THEN id.I18NString
ELSE il.I18nString
END AS WKString
,CASE
WHEN ISNULL(il.I18NID, N'') = N''
THEN id.IETFLangCode
ELSE il.IETFLangCode
END AS IETFLangCode
,dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS') AS I18NID
,dbo.UserI18N_Session_Locale_Key() AS IETFSessionLangCode
,dbo.UserI18N_Database_Locale_Key() AS IETFDatabaseLangCode
FROM UserWKStringBASE b
LEFT OUTER JOIN User3StringI18N il
ON (
il.I18NID = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex, N'WKS')
AND il.IETFLangCode = dbo.UserI18N_Session_Locale_Key()
)
LEFT OUTER JOIN User3StringI18N id
ON (
id.I18NID = dbo.User3StringI18N_KeyValue(b.WKType, b.WKIndex,N'WKS')
AND id.IETFLangCode = dbo.UserI18N_Database_Locale_Key()
)
GO
Inilah sebabnya mengapa UDF
s digunakan sebagai JOIN
predikat. The I18NID
kolom dibentuk dengan menggabungkan:STRING + [ + ID + | + ID + ]
Selama pengujian ini, sederhana SELECT
dari tampilan mengembalikan ~ 309 baris, dan membutuhkan 900-1400ms untuk mengeksekusi. Jika saya membuang string ke tabel lain dan menampar indeks di atasnya, pilih kembali yang sama dalam 20-75ms.
Jadi, cerita panjang pendek (dan saya harap Anda menghargai beberapa kebodohan ini) Saya ingin menjadi orang Samaria yang baik dan mendesain ulang dan menulis ulang ini untuk 99% klien yang menjalankan produk ini yang tidak menggunakan lokalisasi sama sekali- pengguna akhir diharapkan untuk menggunakan [en-US]
lokal bahkan ketika bahasa Inggris adalah bahasa 2/3 .
Karena ini adalah peretasan tidak resmi, saya memikirkan yang berikut:
- Buat tabel String baru yang diisi dengan set data yang digabungkan dengan rapi dari tabel dasar asli
- Buat indeks tabelnya.
- Buat set pengganti tampilan tingkat atas dalam tumpukan yang menyertakan
NVARCHAR
danINT
kolom untukWKType
danWKIndex
kolom. - Ubah beberapa
UDF
s yang mereferensikan pandangan ini untuk menghindari konversi tipe dalam beberapa predikat gabungan (tabel audit terbesar kami adalah 500-2.000 juta baris dan menyimpan sebuahINT
dalamNVARCHAR(4000)
kolom yang digunakan untuk bergabung denganWKIndex
kolom (INT
).) - Schemabind pandangan
- Tambahkan beberapa indeks ke tampilan
- Bangun kembali pemicu pada tampilan menggunakan set logika, bukan kursor
Sekarang, pertanyaan aktual saya:
- Apakah ada metode praktik terbaik untuk menangani string lokal melalui tampilan?
- Alternatif apa yang ada untuk menggunakan
UDF
sebuah rintisan? (Saya dapat menulis spesifikVIEW
untuk setiap pemilik skema dan meng-hard-code bahasa daripada mengandalkan berbagaiUDF
bertopik.) - Bisakah pandangan ini dibuat secara deterministik dengan memenuhi syarat sepenuhnya pada nested
UDF
s dan kemudian menyusun skema tumpukan view?
UDF
definisi Anda juga. Juga, lihat Fungsi yang Ditentukan Pengguna T-SQL: yang baik, yang buruk, dan yang jelekJawaban:
Melihat kode yang diberikan, kita dapat mengatakan,
Kedua, UDF tidak harus sering dipanggil untuk kolom yang sama. Di sini, itu disebut sekali di pilih
dan kedua kalinya untuk bergabung
Satu dapat menghasilkan nilai dalam tabel sementara atau menggunakan CTE (Common Table Expression) untuk mendapatkan nilai-nilai itu di tempat pertama sebelum bergabung terjadi.
Saya telah menghasilkan sampel USP yang akan memberikan beberapa peningkatan:
Silakan coba ini
sumber