Kami berada di pertengahan siklus antara rilis, di mana kami belum mendengar tentang fitur yang direncanakan untuk SQL Server vNext. Ini mungkin waktu terbaik untuk menekan Microsoft untuk perbaikan, selama kami dapat mendukung permintaan kami dengan kasus bisnis yang sah. Di SQL Server 2016, STRING_SPLIT
memecahkan celah yang sudah lama hilang dalam bahasa yang, memang, tidak dimaksudkan untuk pemrosesan string yang rumit. Dan itulah yang ingin saya kemukakan hari ini.
Selama bertahun-tahun sebelum SQL Server 2016 (dan selama bertahun-tahun sejak itu), kami telah menulis versi kami sendiri, meningkatkannya dari waktu ke waktu, dan bahkan berdebat tentang siapa yang tercepat. Kami membuat blog tentang setiap mikrodetik yang bisa kami peroleh dan saya, misalnya, telah menyatakan beberapa kali, "ini adalah posting terakhir saya tentang pemisahan string!" Namun di sinilah kita.
Saya akan selalu berpendapat bahwa parameter bernilai tabel adalah cara yang tepat untuk memecah string. Tapi sementara saya percaya gumpalan teks yang dipisahkan koma ini tidak boleh diekspos ke database dalam bentuk itu, pemisahan string terus menjadi kasus penggunaan yang umum — beberapa posting blog saya di sini berada di 5 teratas dalam tampilan setiap hari .
Jadi, mengapa orang masih mencoba membagi string dengan fungsi bernilai tabel ketika ada pengganti yang lebih unggul? Beberapa, saya yakin, karena mereka masih menggunakan versi yang lebih lama, terjebak di tingkat kompatibilitas yang lebih lama, atau tidak bisa lepas dari pemisahan string sama sekali karena TVP tidak didukung oleh bahasa atau ORM mereka. Selebihnya, selagi STRING_SPLIT
nyaman dan efisien, itu tidak sempurna. Ini memiliki batasan yang membawa beberapa gesekan dan yang membuat penggantian panggilan fungsi yang ada dengan panggilan asli menjadi rumit atau tidak mungkin.
Ini daftar saya.
Batasan ini tidak lengkap, tetapi saya telah mencantumkan yang penting di saya urutan prioritas (dan Andy Mallon membuat blog tentang ini hari ini juga):
- Pembatas satu karakter
Tampaknya fungsi tersebut dibuat hanya dengan menggunakan kasus mati-sederhana dalam pikiran:CSV. Orang memiliki string yang lebih kompleks daripada1,2,3
atauA|B|C
, dan mereka sering diumpankan ke database mereka dari sistem di luar kendali mereka. Seperti yang saya jelaskan dalam jawaban ini dan tip ini , ada cara untuk mengatasi ini (operasi penggantian yang benar-benar tidak efisien), tetapi mereka benar-benar jelek dan, sejujurnya, membatalkan semua manfaat kinerja yang ditawarkan oleh implementasi asli. Juga, beberapa gesekan dengan yang satu ini secara khusus bermuara pada:"Nah,string_to_array
PostgreSQL menangani beberapa pembatas karakter, jadi mengapa SQL Server tidak bisa?" Implementasi:Tingkatkan ukuran maksimalseparator
. - Tidak ada indikasi urutan input
Keluaran dari fungsi tersebut adalah himpunan dan, secara inheren, himpunan tidak memiliki urutan. Dan sementara dalam kebanyakan kasus Anda akan melihat string input sepertibob,ted,frank
keluar dalam urutan itu (bob
ted
frank
), tidak ada jaminan (dengan atau tanpa(ORDER BY (SELECT NULL))
yang ceroboh meretas). Banyak fungsi yang dibuat di rumah menyertakan kolom keluaran untuk menunjukkan posisi ordinal dalam string, yang dapat menjadi penting jika daftar disusun dalam urutan yang ditentukan atau posisi ordinal yang tepat memiliki beberapa arti. Implementasi:Tambahkan opsi untuk menyertakan kolom posisi ordinal di hasil. - Jenis keluaran hanya berdasarkan masukan
Kolom keluaran fungsi ditetapkan ke salah satuvarchar
ataunvarchar
, dan ditentukan secara tepat oleh panjang seluruh string input, bukan panjang elemen terpanjang. Jadi, Anda memiliki daftar 25 huruf, jenis outputnya adalah setidaknyavarchar(51)
. Untuk string yang lebih panjang, ini dapat menyebabkan masalah dengan pemberian memori, tergantung pada penggunaan, dan dapat menimbulkan masalah jika konsumen bergantung pada tipe data lain yang menjadi keluaran (misalnya,int
, yang fungsinya terkadang ditentukan untuk menghindari konversi implisit nanti). Sebagai solusinya, pengguna terkadang membuat tabel temp atau variabel tabel mereka sendiri, dan membuang output fungsi di sana sebelum berinteraksi dengannya, yang dapat menyebabkan masalah kinerja. Implementasi:Tambahkan opsi untuk menentukan jenis output nilaivalue
. - Tidak dapat mengabaikan elemen kosong atau pembatas tambahan
Bila Anda memiliki string sepertia,,,b,
, Anda mungkin mengharapkan hanya dua elemen yang akan dihasilkan, karena tiga elemen lainnya kosong. Sebagian besar TVF khusus yang pernah saya lihat memangkas pembatas tambahan dan/atau memfilter string tanpa panjang, tetapiSTRING_SPLIT
mengembalikan semua 5 baris. Hal ini membuat sulit untuk menukar fungsi asli karena Anda juga harus menambahkan logika pembungkus untuk menghilangkan entitas ini. Implementasi:Tambahkan opsi untuk mengabaikan elemen kosong. - Tidak dapat memfilter duplikat
Ini mungkin permintaan yang kurang umum, dan mudah diselesaikan dengan menggunakanDISTINCT
atauGROUP BY
, tetapi banyak fungsi melakukan ini secara otomatis untuk Anda. Tidak ada perbedaan nyata dalam kinerja dalam kasus ini, tetapi ada sesuatu yang Anda lupa tambahkan sendiri (pikirkan daftar besar, dengan banyak duplikat, bergabung ke tabel besar). Implementasi:Tambahkan opsi untuk memfilter duplikat.
Ini kasus bisnisnya.
Semua itu terdengar teoretis, tetapi inilah kasus bisnisnya, yang dapat saya jamin sangat nyata. Di Wayfair, kami memiliki sejumlah besar SQL Server, dan kami memiliki lusinan tim berbeda yang telah membuat fungsi bernilai tabel mereka sendiri selama bertahun-tahun. Beberapa lebih baik daripada yang lain, tetapi semuanya dipanggil dari ribuan baris kode. Kami baru-baru ini memulai proyek di mana kami mencoba menggantinya dengan panggilan ke STRING_SPLIT
, tetapi kami mengalami kasus pemblokiran melibatkan beberapa batasan di atas.
Beberapa mudah untuk diselesaikan, menggunakan fungsi pembungkus. Tapi pembatas karakter tunggal batasan memaksa kami untuk mengevaluasi solusi yang buruk menggunakan REPLACE
, dan ini terbukti menghilangkan manfaat kinerja yang kami harapkan, membuat kami memompa rem. Dan dalam kasus tersebut, kami kehilangan kunci tawar-menawar dalam mendorong peningkatan ke tingkat kompatibilitas (tidak semua database berada di 130, apalagi 140). Dalam hal ini, kami tidak hanya kehilangan STRING_SPLIT
peningkatan, tetapi juga pada 130+ peningkatan kinerja lainnya yang akan kami nikmati jika STRING_SPLIT
sudah cukup menarik dengan sendirinya untuk mendorong peningkatan tingkat kompatibilitas.
Jadi, saya meminta bantuan Anda.
Silakan kunjungi item umpan balik ini:
- STRING_SPLIT fitur belum lengkap
Pilih! Lebih penting lagi, tinggalkan komentar menggambarkan kasus penggunaan nyata yang Anda miliki yang membuat STRING_SPLIT
rasa sakit atau non-starter untuk Anda. Suara saja tidak cukup, tetapi dengan umpan balik yang cukup nyata dan kualitatif, ada kemungkinan mereka mulai menganggap serius kesenjangan ini.
Saya merasa ingin mendukung pembatas multi-karakter (bahkan, katakanlah, berkembang dari [n]varchar(1)
ke [n]varchar(5)
) adalah peningkatan yang tidak mengganggu yang akan membuka blokir banyak orang yang berbagi skenario saya. Peningkatan lainnya mungkin lebih sulit untuk diterapkan, beberapa memerlukan kelebihan dan/atau peningkatan bahasa, jadi saya tidak mengharapkan semua perbaikan ini di vNext. Tetapi bahkan satu perbaikan kecil akan menegaskan kembali STRING_SPLIT
adalah investasi yang berharga, dan tidak akan ditinggalkan (seperti, katakanlah, berisi database, salah satu fitur drive-by yang lebih terkenal).
Terima kasih telah mendengarkan!