Database
 sql >> база данни >  >> RDS >> Database

Моля, помогнете с STRING_SPLIT подобрения

Ние сме в средата на цикъла между версиите, когато все още не чуваме за нито една от функциите, планирани за SQL Server vNext. Това е може би най-добрият момент да притиснем Microsoft за подобрения, стига да можем да подкрепим нашите заявки с легитимни бизнес казуси. В SQL Server 2016, STRING_SPLIT разреши дълго липсващата празнина в език, който, разбира се, не беше предназначен за сложна обработка на низове. И това е, което искам да повдигна днес.

Години преди SQL Server 2016 (и години след това) ние пишехме наши собствени версии, подобрявахме ги с течение на времето и дори спорихме кой е най-бързият. Писахме в блогове за всяка микросекунда, която бихме могли да спечелим, и аз, например, няколко пъти съм заявявал:„това е последната ми публикация за разделянето на низове!“ И все пак тук сме.

Винаги ще твърдя, че параметрите с таблично стойности са правилният начин за разделяне на низове. Но докато аз вярвам, че тези разделени със запетая петна от текст никога не трябва да се излагат на базата данни в тази форма, разделянето на низове продължава да е често срещан случай на употреба - няколко от моите публикации в блога тук са в топ 5 по изгледи всеки ден .

И така, защо хората все още се опитват да разделят низове с функции с таблично значение, когато съществува по-добра замяна? Някои, сигурен съм, защото все още са на по-стари версии, заседнали в по-старо ниво на съвместимост или изобщо не могат да се измъкнат от разделяне на низове, защото TVP не се поддържат от техния език или ORM. За останалото, докато STRING_SPLIT е едновременно удобен и ефективен, не е идеален. Той има ограничения, които носят известно триене и правят замяната на съществуващи извиквания на функции с естествено извикване или тромава, или невъзможна.

Ето моя списък.

Тези ограничения не са изчерпателни, но изброих важните в моите приоритетен ред (и Анди Малън също пише за това днес):

  • Ограничител от един знак
    Изглежда, че функцията е създадена само с мъртво прост случай на използване:CSV. Хората имат по-сложни низове от 1,2,3 или A|B|C , и те често се подават към техните бази данни от системи извън техния контрол. Както описвам в този отговор и този съвет, има начини да се заобиколи това (наистина неефективни операции за замяна), но те са наистина грозни и, честно казано, отменят всички предимства на производителността, предлагани от родната реализация. Също така, част от търканията с това се свеждат конкретно до:"Е, string_to_array на PostgreSQL обработва множество разделители на знаци, така че защо не може SQL Server?" Внедряване:Увеличете максималния размер на separator .
  • Няма индикация за реда на въвеждане
    Изходът на функцията е множество и по своята същност множествата нямат ред. И докато в повечето случаи ще видите входен низ като bob,ted,frank излизайте в този ред (bob ted frank ), няма гаранция (със или без небрежно (ORDER BY (SELECT NULL)) хак). Много вградени функции включват изходна колона за указване на порядковата позиция в низа, което може да бъде важно, ако списъкът е подреден в определен ред или точната порядкова позиция има някакво значение. Внедряване:Добавете опция за включване на колона с редна позиция в изхода.
  • Типът на изхода се основава само на вход
    Изходната колона на функцията е фиксирана към varchar или nvarchar , и се определя точно от дължината на целия входен низ, а не от дължината на най-дългия елемент. И така, имате списък от 25 букви, типът на изхода е най-малко varchar(51) . За по-дълги низове това може да доведе до проблеми с предоставянето на памет, в зависимост от употребата, и може да създаде проблеми, ако потребителят разчита на извеждан друг тип данни (да речем, int , които функциите понякога посочват, за да се избегнат неявни преобразувания по-късно). Като заобиколно решение, потребителите понякога създават свои собствени временни таблици или таблични променливи и изхвърлят изхода на функцията там, преди да взаимодействат с нея, което може да доведе до проблеми с производителността. Внедряване:Добавете опция за определяне на изходния тип на value .
  • Не може да се игнорират празни елементи или крайни разделители
    Когато имате низ като a,,,b, , може да очаквате да бъдат изведени само два елемента, тъй като другите три са празни. Повечето персонализирани TVF, които съм виждал, отрязват крайните разделители и/или филтрират низове с нулева дължина, но STRING_SPLIT връща всичките 5 реда. Това затруднява размяната в родната функция, защото трябва да добавите и логика за обвиване, за да елиминирате тези обекти. Внедряване:Добавете опция за игнориране на празни елементи.
  • Не може да се филтрират дубликати
    Това вероятно е по-рядко срещана заявка и лесна за решаване с помощта на DISTINCT или GROUP BY , но много функции правят това автоматично вместо вас. Няма реална разлика в производителността в тези случаи, но има, ако е нещо, което сте забравили да добавите сами (помислете за голям списък, с много дубликати, присъединяване към голяма таблица).

    Внедряване:Добавете опция за филтриране на дубликати.

Ето бизнес казус.

Всички те звучат теоретично, но ето бизнес казуса, който мога да ви уверя, че е много реален. В Wayfair разполагаме със значителна собственост на SQL Server и имаме буквално десетки различни екипи, които са създали свои собствени функции с стойност на таблица през годините. Някои са по-добри от други, но всички те се извикват от хиляди и хиляди редове код. Наскоро стартирахме проект, в който се опитваме да ги заменим с извиквания към STRING_SPLIT , нонатъкнахме се на случаи на блокиране включващи няколко от горните ограничения.

Някои са лесни за заобикаляне, като се използва функция за обвивка. Но единичният разделител ограничението ни принуди да оценим ужасното решение с помощта на REPLACE и това се оказа, че елиминира ползата от производителността, която очаквахме, което ни накара да натиснем спирачките. И в тези случаи загубихме ключова разменна монета в настояването за надстройки до ниво на съвместимост (не всички бази данни са на 130, няма значение 140). В тези случаи губим не само от STRING_SPLIT подобрения, но и на други над 130 подобрения в производителността, на които ще се радваме, ако STRING_SPLIT беше достатъчно убедителен сам по себе си, за да настоява за надграждане на compat ниво.

И така, моля за вашата помощ.

Моля, посетете този елемент за обратна връзка:

  • STRING_SPLIT не е завършена функция

Гласувайте! По-важното е, че оставете коментар описвайки реални случаи на употреба, които имате, които правят STRING_SPLIT болка или не начало за вас. Само гласовете не са достатъчни, но с достатъчно осезаема и качествена обратна връзка има шанс те да започнат да приемат тези пропуски сериозно.

Искам да поддържам разделители от няколко знака (дори, да речем, разширяване от [n]varchar(1) към [n]varchar(5) ) е ненатрапчиво подобрение, което ще отблокира много хора, които споделят моя сценарий. Други подобрения може да са по-трудни за прилагане, някои изискват претоварвания и/или езикови подобрения, така че не очаквам всички тези корекции във vNext. Но дори едно незначително подобрение би повторило това STRING_SPLIT беше инвестиция, която си заслужаваше, и че няма да бъде изоставена (като, да речем, съдържащи се бази данни, една от по-известните функции за шофиране).

Благодаря за слушането!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Използване на AT TIME ZONE за коригиране на стар отчет

  2. SQL, добавяне на данни към таблица

  3. Всичко, което трябва да знаете за стандартите за кодиране на SQL заявки

  4. Свързване на MS SQL към IRI Workbench

  5. Неструктурирано съдържание:неизползван източник на гориво за AI и машинно обучение