Database
 sql >> Datenbank >  >> RDS >> Database

Bitte helfen Sie bei STRING_SPLIT Verbesserungen

Wir befinden uns mitten im Zyklus zwischen den Veröffentlichungen, wo wir noch nichts über die geplanten Funktionen erfahren SQL Server-vNext. Dies ist wahrscheinlich der beste Zeitpunkt, um Microsoft zu Verbesserungen zu drängen, solange wir unsere Anfragen mit legitimen Geschäftsfällen untermauern können. In SQL Server 2016 STRING_SPLIT eine lange vermisste Lücke in einer Sprache, die zugegebenermaßen nicht für komplizierte String-Verarbeitung gedacht war. Und das möchte ich heute ansprechen.

Jahre vor SQL Server 2016 (und Jahre danach) haben wir unsere eigenen Versionen geschrieben, sie im Laufe der Zeit verbessert und uns sogar darüber gestritten, wessen am schnellsten war. Wir haben über jede Mikrosekunde gebloggt, die wir gewinnen konnten, und ich habe mehrfach gesagt:"Dies ist mein letzter Beitrag über das Teilen von Saiten!" Doch hier sind wir.

Ich werde immer argumentieren, dass Tabellenwertparameter der richtige Weg sind, um Strings auseinander zu brechen. Aber während ich Ich bin der Meinung, dass diese durch Kommas getrennten Textkleckse niemals in dieser Form der Datenbank zugänglich gemacht werden sollten. Das Teilen von Zeichenfolgen ist weiterhin ein weit verbreiteter Anwendungsfall – einige meiner Blogposts hier sind in den Top 5 der Aufrufe jeden einzelnen Tag .

Warum also versuchen die Leute immer noch, Strings mit Tabellenwertfunktionen zu teilen, wenn es einen besseren Ersatz gibt? Einige, da bin ich mir sicher, weil sie noch auf älteren Versionen laufen, in einem älteren Kompatibilitätslevel stecken bleiben oder überhaupt nicht vom Splitten von Strings wegkommen, weil TVPs von ihrer Sprache oder ORM nicht unterstützt werden. Für den Rest, während STRING_SPLIT bequem und effizient ist, ist es nicht perfekt. Es hat Einschränkungen, die einige Reibungen mit sich bringen und die das Ersetzen bestehender Funktionsaufrufe durch einen nativen Aufruf entweder umständlich oder unmöglich machen.

Hier ist meine Liste.

Diese Einschränkungen sind nicht erschöpfend, aber ich habe die wichtigsten in mein aufgelistet Prioritätsreihenfolge (und Andy Mallon hat heute auch darüber gebloggt):

  • Einzelzeichen-Trennzeichen
    Es scheint, dass die Funktion nur für den absolut einfachen Anwendungsfall entwickelt wurde:CSV. Menschen haben komplexere Zeichenfolgen als 1,2,3 oder A|B|C , und sie werden oft von Systemen außerhalb ihrer Kontrolle in ihre Datenbanken eingespeist. Wie ich in dieser Antwort und diesem Tipp beschreibe, gibt es Möglichkeiten, dies zu umgehen (wirklich ineffiziente Ersetzungsvorgänge), aber sie sind wirklich hässlich und machen ehrlich gesagt alle Leistungsvorteile rückgängig, die die native Implementierung bietet. Einige der Reibungen mit diesem hier beziehen sich insbesondere auf:„Nun, PostgreSQLs string_to_array verarbeitet mehrere Trennzeichen, warum also nicht SQL Server?“Implementierung:Erhöhen Sie die maximale Größe von separator .
  • Keine Angabe der Eingabereihenfolge
    Die Ausgabe der Funktion ist eine Menge, und Mengen haben von Natur aus keine Ordnung. Und in den meisten Fällen sehen Sie eine Eingabezeichenfolge wie bob,ted,frank kommen in dieser Reihenfolge heraus (bob ted frank ), gibt es keine Garantie (mit oder ohne schlampigen (ORDER BY (SELECT NULL)) hacken). Viele selbst erstellte Funktionen enthalten eine Ausgabespalte, um die Ordnungsposition in der Zeichenfolge anzugeben, was wichtig sein kann, wenn die Liste in einer definierten Reihenfolge angeordnet ist oder die genaue Ordnungsposition von Bedeutung ist. Implementierung:Fügen Sie eine Option hinzu, um die Ordnungspositionsspalte einzubeziehen die Ausgabe.
  • Der Ausgabetyp basiert nur auf der Eingabe
    Die Ausgabespalte der Funktion ist entweder auf varchar festgelegt oder nvarchar , und wird genau durch die Länge der gesamten Eingabezeichenfolge bestimmt, nicht durch die Länge des längsten Elements. Sie haben also eine Liste mit 25 Buchstaben, der Ausgabetyp ist mindestens varchar(51) . Bei längeren Zeichenfolgen kann dies je nach Verwendung zu Problemen mit Speicherzuweisungen führen und zu Problemen führen, wenn der Verbraucher auf die Ausgabe eines anderen Datentyps angewiesen ist (z. B. int , die Funktionen manchmal spezifizieren, um spätere implizite Konvertierungen zu vermeiden). Als Problemumgehung erstellen Benutzer manchmal ihre eigenen temporären Tabellen oder Tabellenvariablen und sichern die Ausgabe der Funktion dort, bevor sie damit interagieren, was zu Leistungsproblemen führen kann. Implementierung:Fügen Sie eine Option hinzu, um den Ausgabetyp von value .
  • Leere Elemente oder abschließende Trennzeichen können nicht ignoriert werden
    Wenn Sie eine Zeichenfolge wie a,,,b, haben , erwarten Sie vielleicht, dass nur zwei Elemente ausgegeben werden, da die anderen drei leer sind. Die meisten benutzerdefinierten TVFs, die ich gesehen habe, schneiden nachfolgende Trennzeichen ab und/oder filtern Zeichenfolgen der Länge Null heraus, aber STRING_SPLIT gibt alle 5 Zeilen zurück. Dies macht es schwierig, die native Funktion auszutauschen, da Sie auch Umbruchlogik hinzufügen müssen, um diese Entitäten zu eliminieren. Implementierung:Fügen Sie eine Option hinzu, um leere Elemente zu ignorieren.
  • Duplikate können nicht herausgefiltert werden
    Dies ist wahrscheinlich eine weniger häufige Anfrage und einfach mit DISTINCT zu lösen oder GROUP BY , aber viele Funktionen erledigen dies automatisch für Sie. In diesen Fällen gibt es keinen wirklichen Leistungsunterschied, aber wenn Sie vergessen, sich selbst hinzuzufügen (stellen Sie sich eine große Liste mit vielen Duplikaten vor, die einer großen Tabelle hinzugefügt wird).

    Implementierung:Fügen Sie eine Option hinzu, um Duplikate herauszufiltern.

Hier ist der Business Case.

Das klingt alles theoretisch, aber hier ist der Business Case, von dem ich Ihnen versichern kann, dass er sehr real ist. Bei Wayfair verfügen wir über einen beträchtlichen SQL Server-Bestand und wir haben buchstäblich Dutzende verschiedener Teams, die im Laufe der Jahre ihre eigenen Tabellenwertfunktionen erstellt haben. Einige sind besser als andere, aber sie werden alle aus Tausenden und Abertausenden von Codezeilen aufgerufen. Wir haben kürzlich ein Projekt gestartet, in dem wir versuchen, sie durch Aufrufe von STRING_SPLIT zu ersetzen , aber wir sind auf Blockierungsfälle gestoßen mit mehreren der oben genannten Einschränkungen.

Einige sind mit einer Wrapper-Funktion einfach zu umgehen. Aber das Einzelzeichen-Trennzeichen Einschränkung zwang uns, die schreckliche Problemumgehung mit REPLACE zu evaluieren , und dies hat den erwarteten Leistungsvorteil beseitigt und uns dazu gebracht, die Bremsen zu pumpen. Und in diesen Fällen haben wir einen wichtigen Verhandlungschip verloren, indem wir auf Upgrades auf die Kompatibilitätsstufe gedrängt haben (nicht alle Datenbanken sind auf 130, geschweige denn 140). In diesen Fällen verlieren wir nicht nur bei STRING_SPLIT Verbesserungen, sondern auch über mehr als 130 Leistungsverbesserungen, die wir genießen würden, wenn STRING_SPLIT allein überzeugend genug war, um auf das Kompatibilitäts-Upgrade zu drängen.

Also bitte ich um Ihre Hilfe.

Bitte besuchen Sie dieses Feedback-Element:

  • STRING_SPLIT ist die Funktion nicht vollständig

Stimme zu! Noch wichtiger, hinterlasse einen Kommentar die realen Anwendungsfälle beschreiben, die Sie haben, die STRING_SPLIT machen ein Schmerz oder ein Nichtstarter für Sie. Stimmen allein reichen nicht aus, aber mit genügend konkretem und qualitativem Feedback besteht die Möglichkeit, dass sie anfangen, diese Lücken ernst zu nehmen.

Ich möchte Trennzeichen mit mehreren Zeichen unterstützen (sogar, sagen wir, das Erweitern von [n]varchar(1) zu [n]varchar(5) ) ist eine unaufdringliche Verbesserung, die viele Leute entsperren wird, die mein Szenario teilen. Andere Verbesserungen sind möglicherweise schwieriger zu implementieren, einige erfordern Überladungen und/oder Sprachverbesserungen, daher erwarte ich nicht alle diese Korrekturen in vNext. Aber selbst eine kleine Verbesserung würde diesen STRING_SPLIT wiederholen eine lohnende Investition war und nicht aufgegeben wird (wie zum Beispiel enthaltene Datenbanken, eine der bekannteren Drive-by-Funktionen).

Danke fürs Zuhören!