Database
 sql >> Base de données >  >> RDS >> Database

Séparer les cordes :un suivi

Il y a eu beaucoup de commentaires suite à mon article de la semaine dernière sur le fractionnement des chaînes. Je pense que le point de l'article n'était pas aussi évident qu'il aurait pu l'être:que passer beaucoup de temps et d'efforts à essayer de "perfectionner" une fonction de fractionnement intrinsèquement lente basée sur T-SQL ne serait pas bénéfique. Depuis, j'ai récupéré la version la plus récente de la fonction de fractionnement de chaînes de Jeff Moden et je l'ai comparée aux autres :

ALTER FUNCTION [dbo].[DelimitedSplitN4K]
(@pString NVARCHAR(4000), @pDelimiter NCHAR(1))
RETURNS TABLE WITH SCHEMABINDING AS
 RETURN
  WITH E1(N) AS (
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
  ),
  E2(N) AS (SELECT 1 FROM E1 a, E1 b),
  E4(N) AS (SELECT 1 FROM E2 a, E2 b), 
  cteTally(N) AS (SELECT TOP (ISNULL(DATALENGTH(@pString)/2,0)) 
    ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4),
  cteStart(N1) AS (SELECT 1 UNION ALL 
    SELECT t.N+1 FROM cteTally t WHERE SUBSTRING(@pString,t.N,1) = @pDelimiter
  ),
cteLen(N1,L1) AS(SELECT s.N1,
    ISNULL(NULLIF(CHARINDEX(@pDelimiter,@pString,s.N1),0)-s.N1,4000)
    FROM cteStart s
  )
 SELECT ItemNumber = ROW_NUMBER() OVER(ORDER BY l.N1),
        Item       = SUBSTRING(@pString, l.N1, l.L1)
   FROM cteLen l;
GO

(Les seules modifications que j'ai apportées :je l'ai formaté pour l'affichage et j'ai supprimé les commentaires. Vous pouvez récupérer la source d'origine ici.)

J'ai dû faire quelques ajustements à mes tests pour représenter fidèlement la fonction de Jeff. Plus important encore :j'ai dû supprimer tous les échantillons impliquant des chaînes> 4 000 caractères. J'ai donc changé les chaînes de 5 000 caractères dans la table dbo.strings en 4 000 caractères à la place, et je me suis concentré uniquement sur les trois premiers scénarios non MAX (en conservant les résultats précédents pour les deux premiers et en exécutant à nouveau les troisièmes tests pour le nouveau longueurs de chaîne de 4 000 caractères). J'ai également supprimé le tableau des nombres de tous les tests sauf un, car il était clair que les performances y étaient toujours pires d'un facteur d'au moins 10. Le tableau suivant montre les performances des fonctions dans chacun des quatre tests, encore une fois en moyenne sur 10 exécutions et toujours avec un cache froid et des tampons propres.

Voici donc mes méthodes préférées légèrement révisées, pour chaque type de tâche :

Vous remarquerez que CLR est resté ma méthode de choix, sauf dans le cas où le fractionnement n'a pas de sens. Et dans les cas où le CLR n'est pas une option, les méthodes XML et CTE sont généralement plus efficaces, sauf dans le cas du fractionnement d'une seule variable, où la fonction de Jeff peut très bien être la meilleure option. Mais étant donné que je pourrais avoir besoin de prendre en charge plus de 4 000 caractères, la solution de table Numbers pourrait bien revenir sur ma liste dans des situations spécifiques où je ne suis pas autorisé à utiliser CLR.

Je promets que mon prochain article sur les listes ne parlera pas du tout de fractionnement, via T-SQL ou CLR, et montrera comment simplifier ce problème quel que soit le type de données.

En passant, j'ai remarqué ce commentaire dans l'une des versions des fonctions de Jeff qui a été posté dans les commentaires :je remercie également celui qui a écrit le premier article que j'ai jamais vu sur les "tables de nombres" qui se trouve à l'URL suivante et à Adam Machanic pour m'y avoir conduit il y a de nombreuses années. -tableau-des-numeros-auxiliaires.html


Cet article a été écrit par moi en 2004. Donc, quiconque a ajouté le commentaire à la fonction, vous êtes le bienvenu. :-)