sql >> Databáze >  >> RDS >> Database

Štípací struny:Následné

Po mém příspěvku z minulého týdne se objevilo mnoho komentářů o dělení strun. Myslím, že pointa článku nebyla tak zřejmá, jak by mohla být:že strávit spoustu času a úsilí snahou „zdokonalit“ přirozeně pomalou rozdělovací funkci založenou na T-SQL by nebylo přínosné. Od té doby jsem shromáždil nejnovější verzi funkce pro dělení řetězců Jeffa Modena a porovnal jsem ji s ostatními:

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

(Jediné změny, které jsem provedl:Naformátoval jsem jej pro zobrazení a odstranil jsem komentáře. Původní zdroj můžete získat zde.)

Musel jsem udělat pár úprav ve svých testech, abych věrně reprezentoval Jeffovu funkci. A co je nejdůležitější:musel jsem zahodit všechny vzorky, které zahrnovaly jakékoli řetězce> 4 000 znaků. Změnil jsem tedy řetězce 5 000 znaků v tabulce dbo.strings na 4 000 znaků a soustředil jsem se pouze na první tři scénáře bez MAX (u prvních dvou jsem ponechal předchozí výsledky a pro nový jsem znovu provedl třetí testy délka řetězce 4 000 znaků). Ze všech testů kromě jednoho jsem také vypustil tabulku Numbers, protože bylo jasné, že výkon tam byl vždy minimálně 10krát horší. Následující graf ukazuje výkon funkcí v každém ze čtyř testů, opět v průměru za 10 spuštění a vždy s chladnou mezipamětí a čistými vyrovnávací paměti.

Zde jsou mé mírně upravené preferované metody pro každý typ úlohy:

Všimnete si, že CLR zůstalo mou volbou, s výjimkou jednoho případu, kdy rozdělení nedává smysl. A v případech, kdy CLR není možností, jsou metody XML a CTE obecně efektivnější, s výjimkou případu rozdělení jedné proměnné, kde může být Jeffova funkce velmi dobře tou nejlepší volbou. Ale vzhledem k tomu, že možná budu potřebovat podporovat více než 4 000 znaků, může se řešení tabulky Numbers vrátit zpět do mého seznamu ve specifických situacích, kdy nesmím používat CLR.

Slibuji, že můj další příspěvek obsahující seznamy nebude vůbec hovořit o rozdělování prostřednictvím T-SQL nebo CLR a ukáže, jak tento problém zjednodušit bez ohledu na typ dat.

Mimochodem, všiml jsem si tohoto komentáře v jedné z verzí Jeffových funkcí, která byla zveřejněna v komentářích:Také děkuji tomu, kdo napsal první článek, který jsem kdy viděl, o „tabulkách čísel“, který se nachází na následující adrese URL, a Adamu Machanicovi za to, že mě k tomu před mnoha lety přivedl.
http://web.archive.org/web/20150411042510/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an -pomocná-tabulka-cisel.html


Ten článek jsem napsal v roce 2004. Takže kdo přidal komentář k funkci, není zač. :-)


  1. Neočekávaná klastrovaná indexová fragmentace

  2. Funkce rozdělení v oracle na hodnoty oddělené čárkou s automatickou sekvencí

  3. Jak Now() funguje v PostgreSQL

  4. Ekvivalent varchar(max) v MySQL?