sql >> Databasteknik >  >> RDS >> Database

Splitting Strings:En uppföljning

Det kom många kommentarer efter mitt inlägg förra veckan om strängdelning. Jag tror att poängen med artikeln inte var så uppenbar som den kunde ha varit:att spendera mycket tid och ansträngning på att försöka "perfektera" en i sig långsam uppdelningsfunktion baserad på T-SQL skulle inte vara fördelaktigt. Jag har sedan dess samlat den senaste versionen av Jeff Modens strängdelningsfunktion och ställt den mot de andra:

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

(De enda ändringarna jag har gjort:jag har formaterat den för visning och jag har tagit bort kommentarerna. Du kan hämta originalkällan här.)

Jag var tvungen att göra ett par justeringar av mina tester för att rättvist representera Jeffs funktion. Viktigast av allt:jag var tvungen att kassera alla prover som involverade strängar> 4 000 tecken. Så jag ändrade strängarna på 5 000 tecken i tabellen dbo.strings till 4 000 tecken istället och fokuserade bara på de tre första scenarierna som inte var MAX (behöll de tidigare resultaten för de två första och kör de tredje testerna igen för de nya 4 000 tecken långa strängar). Jag tappade också tabellen Numbers från alla tester utom ett, eftersom det var tydligt att prestandan där alltid var sämre med en faktor på minst 10. Följande diagram visar prestandan för funktionerna i vart och ett av de fyra testerna, igen. i genomsnitt över 10 körningar och alltid med en kall cache och rena buffertar.

Så här är mina något reviderade föredragna metoder för varje typ av uppgift:

Du kommer att märka att CLR har förblivit min valmetod, förutom i det ena fallet där uppdelning inte är meningsfullt. Och i de fall där CLR inte är ett alternativ, är XML- och CTE-metoderna generellt sett mer effektiva, förutom vid delning av en variabel, där Jeffs funktion mycket väl kan vara det bästa alternativet. Men med tanke på att jag kan behöva stödja mer än 4 000 tecken, kan Numbers-tabelllösningen komma tillbaka till min lista i specifika situationer där jag inte får använda CLR.

Jag lovar att mitt nästa inlägg som involverar listor inte kommer att tala om uppdelning alls, via T-SQL eller CLR, och kommer att visa hur man förenklar detta problem oavsett datatyp.

Till skillnad från detta märkte jag den här kommentaren i en av versionerna av Jeffs funktioner som publicerades i kommentarerna:Jag tackar också den som skrev den första artikeln jag någonsin såg om "nummertabeller" som finns på följande URL och till Adam Machanic för att jag ledde mig till det för många år sedan.
http://web.archive.org/web/20150411042510/http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an -hjälpnummer-tabell.html


Den artikeln skrevs av mig 2004. Så den som lagt till kommentaren till funktionen är välkommen. :-)


  1. Hur kan jag skriva SQL för en tabell som har samma namn som ett skyddat nyckelord i MySql?

  2. MySQL-kommandon för säkerhetskopiering och återställning för databasadministration

  3. MySQL Performance Benchmarking:MySQL 5.7 vs MySQL 8.0

  4. Infoga en tidsstämpel i databasen via ContentValues