T sql glidande medelvärde


Låt oss säga att du har ett bord med cirka 5 miljoner poster och en nvarchar (max) kolumn som är fylld med stor textdata. Du vill ställa in denna kolumn till NULL om någon annan kolumn 1 på snabbast möjliga sätt. Den brute force UPDATE fungerar inte så bra här eftersom det kommer att skapa stor implicit transaktion och ta för alltid. Att göra uppdateringar i små satser på 50K-poster i taget fungerar men det tar fortfarande 47 timmar att slutföra på beefy 32 core64GB-servern. Finns det något sätt att göra den här uppdateringen snabbare Finns det några tips för magiska sökfrågor som offrar någonting annat (till exempel samtidighet) i utbyte mot hastighet OBS! Att skapa tempotabell eller tempokolumn är inte ett alternativ eftersom denna nvarchar (max) kolumn involverar mycket av data och förbrukar så mycket utrymme PS: Ja, SomeOtherColumn är redan indexerad. Jag håller med om att vi regelbundet gör uppdateringar så här på tabeller med 50Million eller till och med 500Million-poster och det händer om några sekunder. Jag skulle gissa att den valda sökplanen inte är mycket optimal och tar mycket tid. Jag har haft det här med mig när det finns en utländsk nyckelbegränsning på ett annat bord på en oindexerad kolumn. Efter att ha tittat på frågeplanen insåg vi att den var tvungen att skanna den andra tabellen för varje radering som var den skyldige. Det hade 23 miljoner rader, indexering av den andra tabellen som togs bort till under 5 sekunder. ndash Cobusve 7 Jun 10 kl 10:46 Från allt jag kan se ser det inte ut som att dina problem är relaterade till index. Nyckeln verkar vara i det faktum att ditt nvarchar (max) fält innehåller mycket data. Tänk på vad SQL måste göra för att kunna utföra denna uppdatering. Eftersom kolumnen du uppdaterar är sannolikt mer än 8000 tecken lagras den på sidan, vilket innebär ytterligare ansträngning när du läser den här kolumnen när den inte är NULL. När du kör ett parti på 50000 uppdateringar måste SQL placera detta i en implicit transaktion för att göra det möjligt att rulla tillbaka vid eventuella problem. För att kunna rulla tillbaka måste det lagra det ursprungliga värdet av kolumnen i transaktionsloggen. Antag att (för enkelhets skull) att varje kolumn innehåller i genomsnitt 10 000 byte data, det vill säga att 50 000 rader kommer att innehålla omkring 500 MB data, som måste lagras tillfälligt (i enkelt återställningsläge) eller permanent (i full återställningsläge). Det går inte att inaktivera loggarna eftersom det kommer att äventyra databasintegriteten. Jag körde ett snabbtest på min hunds långsam skrivbord, och löpande satser på till och med 10 000 blir orimligt långsamma, men minskar storleken till 1000 rader, vilket innebär en temporär loggstorlek på cirka 10 MB, fungerade bara snyggt. Jag lade ett bord med 350 000 rader och markerade 50 000 av dem för uppdatering. Detta slutfördes på ungefär 4 minuter, och eftersom det vågar linjärt bör du kunna uppdatera hela 5Million-raderna på min hunds långsamma skrivbord på cirka 6 timmar på min 1 processor 2 GB-skrivbord, så jag förväntar mig något mycket bättre på din biffiga server av SAN eller något. Det kan hända att du vill köra uppdateringsuppsättningen som en markering, välja endast den primära nyckeln och den stora nvarchar-kolumnen och se till att det går så fort som du förväntar dig. Självklart kan flaskhalsen vara andra användare som låser saker eller ifrågasätter på din lagring eller minne på servern, men eftersom du inte nämnde andra användare antar jag att du har DB i enanvändarläge för detta. Som en optimering bör du se till att transaktionsloggarna finns på en annan fysisk diskgrupp än data för att minimera söktider. Detta hjälpte mig verkligen. Jag gick från 2 timmar till 20 minuter med detta. Enligt min erfarenhet, som arbetar i MSSQL 2005, flyttar varje dag (automatiskt) 4 miljoner 46-byte-poster (ingen nvarchar (max)) från en tabell i en databas till en annan tabell i en annan databas ca 20 minuter i en QuadCore 8GB , 2Ghz-server och det skadar inte programmets prestanda. Genom att flytta menar jag INSERT INTO SELECT och sedan DELETE. CPU-användningen går aldrig över 30, även om bordet som raderas har 28M-poster och det gör hela tiden runt 4K-inlägg per minut men inga uppdateringar. Jo, det är mitt fall, det kan variera beroende på din serverbelastning. Anger att uttalanden (dina uppdateringar) kan läsa rader som har ändrats av andra transaktioner men ännu inte begåtts. I mitt fall är posterna läsliga. Jag vet inte vad rg-tsql betyder men här hittar du information om transaktionsisoleringsnivåer i MSSQL. Var alltid försiktig och se till att du förstår följderna av att läsa oöverträffade transaktioner. Ja, din process behöver inte vänta på öppna transaktioner att begå innan du raderar objekt, men självklart om transaktionen inte är åtagit så betyder det att du raderade raden felaktigt. ndash Cobusve Jun 7 10 at 10:43 Om du kör en produktionsmiljö med inte tillräckligt med utrymme för att duplicera alla dina bord tror jag att du letar efter problem förr eller senare. Om du ger lite information om antalet rader med SomeOtherColumn1, kanske vi kan tänka på ett annat sätt, men jag föreslår: 0) Säkerhetskopiera ditt bord 1) Index flaggkolumnen 2) Ange tabellalternativet till inga loggar. om posibel 3) skriv en lagrad procedur för att köra uppdateringarna svarade 2 juni kl 10:17 BTW. kommer du behöva köra denna procedur mer än en gång i ett liv ndash Dr. belisarius 2 juni kl 10:24 Hur ställer du in tabellalternativ till quotno log tranctionsquot ndash user356004 Jun 7 10 på 9:56 Ditt svar 2017 Stack Exchange , IncMesta människor är bekanta med frasen, citthis kommer att döda två fåglar med en stonequot. Om du inte gör det, hänvisar fasen till ett tillvägagångssätt som adresserar två mål i en åtgärd. (Tyvärr är uttrycket i sig ganska obehagligt, eftersom de flesta av oss inte vill kasta stenar på oskyldiga djur) Idag kommer jag att täcka några grunder på två fantastiska funktioner i SQL Server: kolumnstoreindexet (tillgängligt endast i SQL Server Enterprise) och SQL Query Store. Microsoft genomförde faktiskt kolumnstoreindexet i SQL 2012 Enterprise, även om de har förbättrat det i de två senaste utgåvorna av SQL Server. Microsoft introducerade Query Store i SQL Server 2016. Så, vad är dessa funktioner och varför är de viktiga Tja, jag har en demo som introducerar båda funktionerna och visar hur de kan hjälpa oss. Innan jag går vidare täcker jag även detta (och andra SQL 2016-funktioner) i min CODE Magazine-artikel om nya funktioner SQL 2016. Som en grundläggande introduktion kan Columnstore index hjälpa till att påskynda frågor som skannar över stora mängder data och Query Store spårar avrättningar, körningsplaner och runtime statistik som du normalt behöver samla in manuellt. Lita på mig när jag säger att det här är fantastiska funktioner. För den här demo använder jag demo databasen Microsoft Contoso Retail Data Warehouse. Löst taget är Contoso DW som kvoten riktigt stor AdventureWorksquot, med bord som innehåller miljontals rader. (Den största AdventureWorks tabellen innehåller högst 100 000 rader). Du kan ladda ner Contoso DW-databasen här: microsoften-usdownloaddetails. aspxid18279. Contoso DW fungerar väldigt bra när du vill testa prestanda vid frågor mot större tabeller. Contoso DW innehåller ett standarddatabutikfaktablad som heter FactOnLineSales, med 12,6 miljoner rader. Det är verkligen inte det största datalagdbordet i världen, men det är inte heller barn som spelar. Antag att jag vill sammanfatta produktomsättningen för 2009 och rangordna produkterna. Jag kan fråga faktabordet och gå med i tabellen Produkt Dimension och använda en RANK-funktion, så här: Här är en delresultat av de 10 bästa raderna, av Total Sales. På min bärbara dator (i7, 16 GB RAM) tar frågan var som helst 3-4 sekunder att köra. Det kanske inte verkar som världens ände, men vissa användare kan förvänta sig omedelbara resultat (hur du kan se närmaste resultat när du använder Excel mot en OLAP-kub). Det enda index jag för närvarande har på denna tabell är ett klusterindex på en försäljningsnyckel. Om jag tittar på exekveringsplanen, gör SQL Server ett förslag om att lägga till ett täckningsindex till tabellen: Nu, för att SQL Server föreslår ett index betyder det inte att du blindt ska skapa index på varje citatindexquot-meddelande. I det här fallet upptäcker SQL Server att vi filtrerar baserat på år och använder produktnyckel och försäljningsbelopp. Så, SQL Server föreslår ett täckningsindex, med DateKey som indexnyckelfält. Anledningen till att vi kallar detta ett quotcoveringquot-index beror på att SQL Server kommer att citera längs den icke-nyckelfältquot som vi använde i frågan, citationstecken för ridequot. På så sätt behöver SQL Server inte använda tabellen eller det grupperade indexet på alla databasmotorer kan helt enkelt använda täckningsindex för frågan. Omfattande index är populära i vissa datalagrings - och rapporteringsdatascenarier, men de kommer till en kostnad av databasmotorn som behåller dem. Obs! Omfattande index har funnits länge, så jag har ännu inte täckt kolumnstoreindex och Query Store. Så lägger jag till täckningsindex: Om jag återförsöker samma fråga som jag sprang för en stund sedan (den som aggregerade försäljningsbeloppet för varje produkt), tycks frågan ibland springa ungefär en sekund snabbare och jag får en en annan exekveringsplan, en som använder ett Index-sök i stället för en indexskanning (med datumnyckeln på täckningsindexet för att hämta försäljningen för 2009). Så, före Columnstore Index, kan detta vara ett sätt att optimera denna fråga i mycket äldre versioner av SQL Server. Det går lite snabbare än den första, och jag får en exekveringsplan med ett Index Search istället för en Index Scan. Det finns emellertid några problem: De två exekveringsoperatörerna quotIndex Seekquot och quotHash Match (Aggregate) citationstecken både använder väsentligen kvot för rowquot. Föreställ dig detta i ett bord med hundratals miljoner rader. Relaterat, tänk på innehållet i en faktabord: i det här fallet kan ett enda datum nyckelvärde eller ett enda produktnyckelvärde upprepas över hundratusentals rader (kom ihåg att faktatabellen också har nycklar för geografi, marknadsföring, försäljare , etc.) Så, när quotIndex Seekquot och quotHash Matchquot fungerar rad för rad, så gör de övervärden som kan upprepas över många andra rader. Det här är normalt där jag segrade till SQL Server Columnstore indexet, vilket erbjuder ett scenario för att förbättra prestanda för denna fråga på fantastiska sätt. Men innan jag gör det, låt oss gå tillbaka i tiden. Låt oss gå tillbaka till år 2010 när Microsoft introducerade ett tillägg för Excel som kallades PowerPivot. Många kommer säkert ihåg att se demon av PowerPivot för Excel, där en användare kan läsa miljontals rader från en extern datakälla till Excel. PowerPivot skulle komprimera data och tillhandahålla en motor för att skapa pivottabeller och pivotdiagram som utfördes med fantastiska hastigheter mot komprimerade data. PowerPivot använde en in-memory-teknik som Microsoft kallade quotVertiPaqquot. Denna in-minneteknik i PowerPivot skulle i grunden ta dubbla nyckelvärden för företagsnycklar och komprimera dem till en enda vektor. In-memory-tekniken skulle också scanna dessa värden parallellt, i block av flera hundra åt gången. Slutsatsen är att Microsoft bakat en stor mängd prestandaförbättringar i VertiPaq-minnesfunktionen för att vi ska kunna använda, rätt ut ur den proverbiala rutan. Varför tar jag den här lilla spåret ner i minnesfältet Eftersom i SQL Server 2012 implementerade Microsoft en av de viktigaste funktionerna i sin databasmotorhistoria: kolumnstoreindexet. Indexet är egentligen bara ett index i namnet: det är ett sätt att ta ett SQL Server-bord och skapa ett komprimerat kolonnutrymme i minnet som komprimerar dubbla utländska nyckelvärden ner till enstaka vektorvärden. Microsoft skapade också en ny buffertpool för att läsa dessa komprimerade vektorvärden parallellt vilket skapar potentialen för stora prestationsvinster. Så, jag kommer att skapa ett kolumnindex på bordet, och jag kommer se hur mycket bättre (och mer effektivt) frågan går, jämfört med frågan som löper mot täckningsindexet. Så, jag skapar en kopia av FactOnlineSales (I39ll kallar det FactOnlineSalesDetailNCCS) och jag skapar ett kolumnindex på duplikatbordet så att jag vanligtvis bromsar originalbordet och täckningsindexet på något sätt. Därefter skapar jag ett kolumnindex för det nya tabellen: Observera flera saker: Jag har angivit flera utländska nyckelkolumner samt försäljningsbeloppet. Kom ihåg att ett kolumnregister inte är ett traditionellt raderingsindex. Det finns ingen quotkeyquot. Vi indikerar helt enkelt vilka kolumner SQL Server ska komprimera och placera i en kolumn i minnet. För att använda analogi av PowerPivot for Excel när vi skapar ett kolumnindex, berättar vi för SQL Server att det i huvudsak gör samma sak som PowerPivot gjorde när vi importerade 20 miljoner rader till Excel med PowerPivot. Så, I39ll kör språket igen, den här gången använder du igen det duplicerade FactOnlineSalesDetailNCCS-tabellen som innehåller kolumnstoreindexet. Denna fråga körs omedelbart på mindre än en sekund. Och jag kan också säga att även om bordet hade hundratals miljoner rader, skulle det ändå köras på ett ordspråkigt citat av en ögonfrans. Vi kunde titta på exekveringsplanen (och inom några minuter kommer vi), men nu är det dags att täcka funktionen Query Store. Föreställ dig ett ögonblick att vi körde båda frågorna över en natt: den fråga som använde det vanliga FactOnlineSales-tabellen (med täckningsindex) och sedan den fråga som använde dubblettabellen med kolumnstoreindexet. När vi loggar in på följande morgon, vill vi se exekveringsplanen för båda frågorna när de ägde rum, liksom exekveringsstatistiken. Med andra ord tycker vi att vi ser samma statistik som vi kan se om vi körde båda frågorna interaktivt i SQL Management Studio, vände i TIME och IO Statistics, och såg exekveringsplanen direkt efter att exekveringen gjorts. Tja, det är vad Query Store tillåter oss att göra, vi kan aktivera (aktivera) Query Store för en databas, vilket kommer att utlösa SQL Server för att lagra förfrågan och planera statistik så att vi kan se dem senare. Så, jag kommer att aktivera Query Store i Contoso-databasen med följande kommando (och I39ll släcker också eventuellt cachning): Sedan kör jag de två frågorna (och quotequotot som jag sprang dem för några timmar sedan): Låt oss nu låtsas som om de sprang timmar sedan. Enligt vad jag sa kommer Query Store att fånga exekveringsstatistiken. Så hur ser jag dem Lyckligtvis är det ganska enkelt. Om jag utökar Contoso DW-databasen, ser jag en mapp för Query Store. Query Store har enorm funktionalitet och I39ll försöker täcka mycket av det i efterföljande blogginlägg. Men för just nu vill jag se exekveringsstatistik för de två frågorna, och undersöka exekveringsoperatörerna för kolumnindexet. Så, högerklickar du på Top Resource Consuming Queries och kör det alternativet. Det ger mig ett diagram som nedan, där jag kan se exekveringsvaraktighetstid (i millisekunder) för alla frågor som har utförts. I det här fallet var Fråga 1 frågan mot originalbordet med täckningsindexet och Fråge 2 var mot bordet med kolumnhandelindex. Numren ligger inte i kolumnskivans index bättre än det ursprungliga bordsskyddsindexet med en faktor på nästan 7 till 1. Jag kan ändra mätvärdet för att se minnesförbrukningen istället. Observera i det här fallet att fråga 2 (kolumnhandelindexfrågan) använde mycket mer minne. Detta visar tydligt varför kolonnekatalyset representerar quotin-memoryquot-teknik. SQL Server laddar hela kolumnregistret i minnet och använder en helt annan buffertpool med förbättrade operatörer för att bearbeta indexet. OK, så vi har några grafer för att visa exekveringsstatistik kan vi se exekveringsplanen (och exekveringsoperatörer) som är associerade med varje utförande. Ja, det kan vi. Om du klickar på den vertikala fältet för den fråga som använde kolumnklassindexet ser du utförandet planera nedan. Det första som vi ser är att SQL Server utförde en kolumnskriftsindexsökning, och det representerade nästan 100 av kostnaden för frågan. Du kanske säger, en minut, den första frågan använde ett täckningsindex och utförde ett index sök så hur kan en kolumnskriftsindexsökning bli snabbare? Det är en legitim fråga, och lyckligtvis finns det ett svar. Även när den första frågan utförde en indexsökning, utfördes den fortfarande quad för radquot. Om jag lägger muspekaren över skivoperatörskatalogoperatören ser jag ett verktygstips (som nedan) med en viktig inställning: Exekveringsläget är BATCH (i motsats till ROW. Vilket är vad vi hade med den första frågan med hjälp av täcker index). Det BATCH-läget berättar för oss att SQL Server hanterar komprimerade vektorer (för eventuella utländska nyckelvärden som dupliceras, till exempel produktnyckel och datumnyckel) i satser på nästan 1000 parallellt. Så SQL Server kan fortfarande bearbeta kolumnkatalogen mycket effektivare. Om jag också placerar musen över Hash Match (Aggregate) - uppgiften ser jag också att SQL Server samlar in kolumnhandelindex med Batch-läge (även om operatören själv representerar en så liten procent av kostnaden för frågan) Slutligen kan fråga, quotOK, så SQL Server komprimerar värdena i data, behandlar värdena som vektorer och läser dem i block med nästan tusen värden parallellt men min fråga bara önskade data för 2009. Så är SQL Server-skanning över hela uppsättningen dataquot igen, en bra fråga. Svaret är, inte riktigt. Lyckligtvis för oss utför den nya kolumnhandelens indexbuffertpool en annan funktion som kallas kvotsegment eliminationquot. I grund och botten kommer SQL Server att undersöka vektorns värden för kolumnen datum kolumn i kolumnkatalogen och eliminera segment som ligger utanför årets år 2009. Jag slutar här. I efterföljande blogginlägg täcker I39ll både kolumnbutikindex och Query Store mer detaljerat. Det som vi sett här idag är att Columnstore-indexet kan påskynda frågor som skannar över stora mängder data, och Query Store kommer att fånga förfrågningar och låta oss granska exekverings - och resultatstatistik senare. Till slut vill vi producera en resultatuppsättning som visar följande. Notera tre saker: Kolumnerna pivotar väsentligen alla möjliga returförklaringar, efter att ha visat försäljningsbeloppet. Resultatet innehåller subtotaler vid veckans slutdatum (söndag) för alla klienter (där kunden är NULL) Resultatet innehåller en total summa rad (där kunden och datumet är båda NULL) Först innan jag kommer in i SQL-änden kunde vi använda den dynamiska pivotmatrixfunktionen i SSRS. Vi skulle helt enkelt behöva kombinera de två resultatuppsättningarna med en kolumn och sedan kunde vi mata resultaten till SSRS-matriskontrollen, som kommer att sprida returskälen över kolumnns axel i rapporten. Men inte alla använder SSRS (även om de flesta borde). Men även då måste utvecklare ibland konsumera resultatuppsättningar i något annat än ett rapporteringsverktyg. Så för det här exemplet, låt oss antar att vi vill generera resultatuppsättningen för en webbgrid sida och eventuellt vill utvecklaren citera outquot de subtotala raderna (där jag har ett ResultatSetNum-värde på 2 och 3) och placera dem i ett sammanfattande rutnät. Så bunden måste vi generera produktionen ovan direkt från en lagrad procedur. Och som en extra twist nästa vecka kan det vara Retur Reason X och Y och Z. Så vi vet inte hur många återvändande skäl det kan vara. Vi vill enkelt att frågan ska svänga på de möjliga distinkta värdena för Return Reason. Här är där T-SQL PIVOT har en begränsning som vi behöver för att ge de möjliga värdena. Eftersom vi vet att det fram till körtid måste vi generera frågesträngen dynamiskt med hjälp av det dynamiska SQL-mönstret. Det dynamiska SQL-mönstret innebär att man skapar syntaxen, bit för bit, lagrar den i en sträng och sedan utför strängen i slutet. Dynamisk SQL kan vara knepigt, eftersom vi måste bädda in syntax inuti en sträng. Men i det här fallet är det vårt enda sanna alternativ om vi vill hantera ett varierat antal återvändande skäl. Jag har alltid funnit att det bästa sättet att skapa en dynamisk SQL-lösning är att bestämma vad den quotiedalquot-genererade frågan skulle vara i slutet (i det här fallet, med tanke på de återvändande skälen vi vet om).och sedan omvända det med piecing det tillsammans en del i taget. Och så, här är SQL som vi behöver om vi visste att dessa återgångsskäl (A till D) var statiska och skulle inte förändras. Frågan gör följande: Kombinerar data från SalesData med data från ReturnData, där vi quothard-wirequot ordet Försäljning som en handlingstyp bildar försäljnings tabellen och använder sedan Returförklaringen från Returdata till samma ActionType-kolumn. Det kommer att ge oss en ren ActionType-kolonn på vilken vi kan pivotera. Vi kombinerar de två SELECT-satserna i ett gemensamt tabelluttryck (CTE), vilket i grund och botten är en härledd tabellundersökning som vi sedan använder i nästa uttalande (till PIVOT) Ett PIVOT-uttalande mot CTE, som summerar dollar för åtgärdstypen vara i ett av de möjliga Action Type-värdena. Observera att detta inte är det slutliga resultatuppsättningen. Vi placerar detta i en CTE som läser från den första CTE. Anledningen till detta är att vi vill göra flera grupperingar i slutet. Det slutliga SELECT-uttalandet, som läses från PIVOTCTE, kombinerar det med en efterföljande fråga mot samma PIVOTCTE, men där vi också implementerar två grupperingar i funktionen GROUPING SETS i SQL 2008: GROUPING vid veckans slutdatum (dbo. WeekEndingDate) GROUPERING för alla rader () Så om vi visste med säkerhet att vi aldrig skulle ha mer returkodskoder, så skulle det vara lösningen. Vi måste dock redogöra för andra orsakskoder. Så vi måste generera hela denna fråga ovan som en stor sträng där vi bygger de möjliga returskälen som en kommaseparerad lista. I39m kommer att visa hela T-SQL-koden för att generera (och exekvera) önskad fråga. Och sedan förstör jag det i delar och förklarar varje steg. Så först, här är hela koden för att dynamiskt generera vad jag har ovanför. Det finns i princip fem steg vi behöver täcka. Steg 1 . Vi vet att någonstans i mixen måste vi skapa en sträng för detta i frågan: SalesAmount, Reason A, Reason B, Reason C, Reason D0160016001600160 Vad vi kan göra är att bygga ett temporärt gemensamt bordsuttryck som kombinerar de hårda kablarna Amountquot kolumn med den unika listan över möjliga orsakskoder. När vi har det i en CTE kan vi använda det trevliga lilla tricket av FOR XML PATH (3939) för att kollapsa dessa rader i en enda sträng, sätt ett kommatecken framför varje rad som frågan läser och använd sedan STUFF för att ersätta den första instansen av ett komma med ett tomt utrymme. Detta är ett knep som du kan hitta i hundratals SQL-bloggar. Så den här första delen bygger en sträng som heter ActionString som vi kan använda längre ner. Steg 2 . Vi vet också att vi vill SUM de genererade pivoterade orsakskolumnerna, tillsammans med standardförsäljningskolonnen. Så vi behöver en separat sträng för det som jag ska ringa SUMSTRING. I39ll använder helt enkelt den ursprungliga ActionString och ersätter sedan de yttre parenteserna med SUM-syntaxen, plus de ursprungliga parenteserna. Steg 3: Nu börjar det verkliga arbetet. Genom att använda den ursprungliga frågan som en modell vill vi generera den ursprungliga frågan (börjar med UNION av de två tabellerna), men ersätta eventuella referenser till svängda kolumner med strängarna som vi dynamiskt genererade ovan. Även om jag inte absolut är skyldig, har jag också skapat en variabel för att helt enkelt göra några kombinationer av returlinjemätningar som vi vill bädda in i den genererade frågan (för läsbarhet). Så we39ll konstruera hela frågan i en variabel som heter SQLPivotQuery. Steg 4. Vi fortsätter att bygga frågan igen och sammanfatta syntaxen vi kan quothard-wirequot med ActionSelectString (som vi genererade dynamiskt för att hålla alla möjliga återgångsgrunder). Steg 5. Slutligen kommer vi att generera den sista delen av Pivot Query, som härstammar från det 2: e vanliga tabelluttrycket (PIVOTCTE, från modellen ovan) och genererar den sista SELECT som ska läsas från PIVOTCTE och kombinerar den med en andra läs mot PIVOTCTE till implementera gruppsätten. Slutligen kan vi quotexecutequot strängen med hjälp av SQL-lagrade proc spexecuteSQL Så hoppas du kan se att processen för att följa för denna typ av ansträngning är att bestämma vad den sista frågan skulle vara, baserat på din nuvarande uppsättning data och värden (dvs byggd en frågemodell) Skriv den nödvändiga T-SQL-koden för att generera den sökfrågan som en sträng. Förmodligen den viktigaste delen är att bestämma den unika uppsättningen värden som du pllot PIVOT, och sedan kollapsa dem i en sträng med hjälp av STUFF-funktionen och FOR XML PATH (3939) trick Så vad är det i mitt sinne idag Tja, minst 13 saker Två somrar sedan skrev jag ett utkast till BDR som delvis fokuserade på utbildningens roll och värdet av en bra liberal konstbakgrund, inte bara för mjukvaruindustrin utan även för andra industrier. En av teman i denna BDR betonade en avgörande och upplyst synpunkt från den kända programarkitekten Allen Holub om liberal konst. Ill (trogen) parafraser hans budskap: han betonade parallellerna mellan programmering och studier av historia genom att påminna alla om att historia läser och skriver (och jag lägger till, identifierar mönster) och mjukvaruutveckling läser och skriver också (och igen, identifierar mönster ). Och så skrev jag en åsikt som fokuserade på detta och andra relaterade ämnen. Men tills idag har jag aldrig kommit runt för att antingen publiceraposting det. Varje så ofta Id tänker på att revidera den, och Id sätter sig ensam i några minuter och gör några justeringar till det. Men då skulle livet i allmänhet komma i vägen och Id slutar aldrig. Så vad förändrats För några veckor sedan skrev kollega CoDe Magazine-kolumnisten och branschledaren Ted Neward ett stycke i sin vanliga kolumn, Managed Coder, som fick min uppmärksamhet. Titeln på artikeln är On Liberal Arts. och jag rekommenderar starkt att alla läser det. Ted diskuterar värdet av en liberal arts bakgrund, den falska dikotomin mellan en liberal arts bakgrund och framgång i mjukvaruutveckling, och behovet av att skriva väl. Han talar om några av sina egna möten med HR-personalledning om hans utbildningsbakgrund. Han betonar också behovet av att acceptera och anpassa sig till förändringar i vår bransch, liksom kännetecknen hos en framgångsrik mjukvarufaglig (vara pålitlig, planera framåt och lära sig att komma över den ursprungliga konflikten med andra lagmedlemmar). Så det är en bra läsning, liksom Teds andra CoDe-artiklar och blogginlägg. Det fick mig också att tänka på mina åsikter om detta (och andra ämnen), och slutligen motiverade mig att avsluta min egen redaktionella. Så, bättre sent än aldrig, här är mitt nuvarande Bakers Dozen of Reflections: Jag säger: Vatten fryser vid 32 grader. Om du är i en träningsinriktad roll kanske du tror att du gör allt i världen för att hjälpa någon när de faktiskt känner att de bara känner en temperatur på 34 grader, och därför stämmer det inte med dem. Ibland tar det bara lite mer ansträngning eller annan ideakemisk katalysator eller ett nytt perspektiv vilket innebär att de med tidigare utbildning kan dra på olika källor. Vatten fryser vid 32 grader. Vissa människor kan behålla höga koncentrationer, även med ett rum fullt av bullriga människor. Jag är inte en av dem ibland behöver jag lite integritet att tänka igenom en kritisk fråga. Vissa beskriver det här som du måste lära dig att gå ifrån det. Stats på ett annat sätt, det är en sökning efter den sällsynta luften. Den senaste veckan spenderade jag timmar i halvt upplyst, tyst rum med whiteboard tills jag helt förstod ett problem. Det var först då jag kunde prata med andra utvecklare om en lösning. Meddelandet här är inte att förkunna hur du ska gå om ditt företag att lösa problem, utan snarare för alla att veta sina styrkor och vad som fungerar och använda dem till din fördel så mycket som möjligt. Vissa fraser är som naglar på en tavla för mig. Använd det som ett undervisningsmoment är en. (Varför är det som naglar på en tavla? Om du är en mentorroll, bör du brukar vara i undervisningsmodus ändå, dock subtilt). Hennes andra jag kan inte förklara det ord, men jag förstår det. Det här låter lite kallt, men om en person verkligen inte kan förklara något i ord, kanske förstår de inte. Visst kan en person ha en fuzzy känsla av hur något fungerar Jag kan bluffa mig genom att beskriva hur en digitalkamera fungerar men sanningen är att jag inte verkligen förstår det så bra. Det finns ett fält som kallas epistemologi (kunskapsstudien). En av de grundläggande förutsättningarna för att förstå huruvida det är en kamera eller ett designmönster - är förmågan att etablera sammanhang, identifiera kedjan av relaterade händelser, attributen till några komponenter längs vägen etc. Ja, förståelse är ibland mycket svårt arbete , men att dyka in i ett ämne och bryta det är värt ansträngningen. Även de som undrar certifieringen kommer att erkänna att processen att studera för certifieringsförsök hjälper till att fylla luckor i kunskap. En databaschef är mer benägen att anställa en databasutvecklare som kan prata extemporaneously (och enkelt) om transaktionsisoleringsnivåer och utlösare, i motsats till någon som vet om det men kämpar för att beskriva deras användning. Theres en annan följd här. Ted Neward rekommenderar att utvecklare tar upp allmänhetens talande, bloggar etc. Jag är överens med 100. Processen med public speaking och blogging kommer i praktiken att tvinga dig att börja tänka på ämnen och bryta ner definitioner som du annars annars skulle ha tagit för givet. För några år sedan trodde jag att jag förstod T-SQL MERGE-uttalandet ganska bra. Men först efter att ha skrivit om det och talade om att fältfrågor från andra som hade perspektiv som aldrig kom till mig att min nivå av förståelse ökade exponentiellt. Jag vet en historia om en anställningschef som en gång intervjuade en författarutvecklare för en kontraktsposition. Anställningschefen var föraktig av publikationer i allmänhet och skällde på sökanden. Så om du ska jobba här, vill du hellre skriva böcker eller skriva kod? Ja, jag erkänner att det i någon bransch kommer att finnas några rena akademiker. Men vad den anställande chefen missade var möjligheterna att stärka och skärpa färdighetssätt. Under rensningen av en gammal låda med böcker kom jag över en skatt från 1980-talet: Programmerare på jobbet. som innehåller intervjuer med en mycket ung Bill Gates, Ray Ozzie och andra kända namn. Varje intervju och varje insikt är värt priset på boken. Enligt min mening var den mest intressanta intervjun med Butler Lampson. vem gav några kraftfulla råd. Till helvetet med datakunskap. Det är helt löjligt. Studera matematik Lär dig att tänka. Läsa. Write. These things are of more enduring value. Learn how to prove theorems: A lot of evidence has accumulated over the centuries that suggests this skill is transferable to many other things. Butler speaks the truth . Ill add to that point learn how to play devils advocate against yourself. The more you can reality-check your own processes and work, the better off youll be. The great computer scientistauthor Allen Holub made the connection between software development and the liberal arts specifically, the subject of history. Here was his point: what is history Reading and writing. What is software development Among other things, reading and writing . I used to give my students T-SQL essay questions as practice tests. One student joked that I acted more like a law professor. Well, just like Coach Donny Haskins said in the movie Glory Road, my way is hard. I firmly believe in a strong intellectual foundation for any profession. Just like applications can benefit from frameworks, individuals and their thought processes can benefit from human frameworks as well. Thats the fundamental basis of scholarship. There is a story that back in the 1970s, IBM expanded their recruiting efforts in the major universities by focusing on the best and brightest of liberal arts graduates. Even then they recognized that the best readers and writers might someday become strong programmersystems analysts. (Feel free to use that story to any HR-type who insists that a candidate must have a computer science degree) And speaking of history: if for no other reason, its important to remember the history of product releases if Im doing work at a client site thats still using SQL Server 2008 or even (gasp) SQL Server 2005, I have to remember what features were implemented in the versions over time. Ever have a favorite doctor whom you liked because heshe explained things in plain English, gave you the straight truth, and earned your trust to operate on you Those are mad skills . and are the result of experience and HARD WORK that take years and even decades to cultivate. There are no guarantees of job success focus on the facts, take a few calculated risks when youre sure you can see your way to the finish line, let the chips fall where they may, and never lose sight of being just like that doctor who earned your trust. Even though some days I fall short, I try to treat my client and their data as a doctor would treat patients. Even though a doctor makes more money There are many clichs I detest but heres one I dont hate: There is no such thing as a bad question. As a former instructor, one thing that drew my ire was hearing someone criticize another person for asking a supposedly, stupid question. A question indicates a person acknowledges they have some gap in knowledge theyre looking to fill. Yes, some questions are better worded than others, and some questions require additional framing before they can be answered. But the journey from forming a question to an answer is likely to generate an active mental process in others. There are all GOOD things. Many good and fruitful discussions originate with a stupid question. I work across the board in SSIS, SSAS, SSRS, MDX, PPS, SharePoint, Power BI, DAX all the tools in the Microsoft BI stack. I still write some code from time to time. But guess what I still spend so much time doing writing T-SQL code to profile data as part of the discovery process. All application developers should have good T-SQL chops. Ted Neward writes (correctly) about the need to adapt to technology changes. Ill add to that the need to adapt to clientemployer changes. Companies change business rules. Companies acquire other companies (or become the target of an acquisition). Companies make mistakes in communicating business requirements and specifications. Yes, we can sometimes play a role in helping to manage those changes and sometimes were the fly, not the windshield. These sometimes cause great pain for everyone, especially the I. T. people. This is why the term fact of life exists we have to deal with it. Just like no developer writes bug-free code every time, no I. T. person deals well with change every single time. One of the biggest struggles Ive had in my 28 years in this industry is showing patience and restraint when changes are flying from many different directions. Here is where my prior suggestion about searching for the rarified air can help. If you can manage to assimilate changes into your thought process, and without feeling overwhelmed, odds are youll be a significant asset. In the last 15 months Ive had to deal with a huge amount of professional change. Its been very difficult at times, but Ive resolved that change will be the norm and Ive tried to tweak my own habits as best I can to cope with frequent (and uncertain) change. Its hard, very hard. But as coach Jimmy Duggan said in the movie A League of Their Own: Of course its hard. If it wasnt hard, everyone would do it. The hard, is what makes it great . A powerful message. Theres been talk in the industry over the last few years about conduct at professional conferences (and conduct in the industry as a whole). Many respected writers have written very good editorials on the topic. Heres my input, for what its worth. Its a message to those individuals who have chosen to behave badly: Dude, it shouldnt be that hard to behave like an adult. A few years ago, CoDe Magazine Chief Editor Rod Paddock made some great points in an editorial about Codes of Conduct at conferences. Its definitely unfortunate to have to remind people of what they should expect out of themselves. But the problems go deeper. A few years ago I sat on a five-person panel (3 women, 2 men) at a community event on Women in Technology. The other male stated that men succeed in this industry because the Y chromosome gives men an advantage in areas of performance. The individual who made these remarks is a highly respected technology expert, and not some bozo making dongle remarks at a conference or sponsoring a programming contest where first prize is a date with a bikini model. Our world is becoming increasingly polarized (just watch the news for five minutes), sadly with emotion often winning over reason. Even in our industry, recently I heard someone in a position of responsibility bash software tool XYZ based on a ridiculous premise and then give false praise to a competing tool. So many opinions, so many arguments, but heres the key: before taking a stand, do your homework and get the facts . Sometimes both sides are partly rightor wrong. Theres only one way to determine: get the facts. As Robert Heinlein wrote, Facts are your single clue get the facts Of course, once you get the facts, the next step is to express them in a meaningful and even compelling way. Theres nothing wrong with using some emotion in an intellectual debate but it IS wrong to replace an intellectual debate with emotion and false agenda. A while back I faced resistance to SQL Server Analysis Services from someone who claimed the tool couldnt do feature XYZ. The specifics of XYZ dont matter here. I spent about two hours that evening working up a demo to cogently demonstrate the original claim was false. In that example, it worked. I cant swear it will always work, but to me thats the only way. Im old enough to remember life at a teen in the 1970s. Back then, when a person lost hisher job, (often) it was because the person just wasnt cutting the mustard. Fast-forward to today: a sad fact of life is that even talented people are now losing their jobs because of the changing economic conditions. Theres never a full-proof method for immunity, but now more than ever its critical to provide a high level of what I call the Three Vs (value, versatility, and velocity) for your employerclients. I might not always like working weekends or very late at night to do the proverbial work of two people but then I remember there are folks out there who would give anything to be working at 1 AM at night to feed their families and pay their bills. Always be yourselfyour BEST self. Some people need inspiration from time to time. Heres mine: the great sports movie, Glory Road. If youve never watched it, and even if youre not a sports fan I can almost guarantee youll be moved like never before. And Ill close with this. If you need some major motivation, Ill refer to a story from 2006. Jason McElwain, a high school student with autism, came off the bench to score twenty points in a high school basketball game in Rochester New York. Heres a great YouTube video. His mother said it all . This is the first moment Jason has ever succeeded and is proud of himself. I look at autism as the Berlin Wall. He cracked it. To anyone who wanted to attend my session at todays SQL Saturday event in DC I apologize that the session had to be cancelled. I hate to make excuses, but a combination of getting back late from Detroit (client trip), a car thats dead (blown head gasket), and some sudden health issues with my wife have made it impossible for me to attend. Back in August, I did the same session (ColumnStore Index) for PASS as a webinar. You can go to this link to access the video (itll be streamed, as all PASS videos are streamed) The link does require that you fill out your name and email address, but thats it. And then you can watch the video. Feel free to contact me if you have questions, at kgoffkevinsgoff November 15, 2013 Getting started with Windows Azure and creating SQL Databases in the cloud can be a bit daunting, especially if youve never tried out any of Microsofts cloud offerings. Fortunately, Ive created a webcast to help people get started. This is an absolute beginners guide to creating SQL Databases under Windows Azure. It assumes zero prior knowledge of Azure. You can go to the BDBI Webcasts of this website and check out my webcast (dated 11102013). Or you can just download the webcast videos right here: here is part 1 and here is part 2. You can also download the slide deck here. November 03, 2013 Topic this week: SQL Server Snapshot Isolation Levels, added in SQL Server 2005. To this day, there are still many SQL developers, many good SQL developers who either arent aware of this feature, or havent had time to look at it. Hopefully this information will help. Companion webcast will be uploaded in the next day look for it in the BDBI Webcasts section of this blog. October 26, 2013 Im going to start a weekly post of T-SQL tips, covering many different versions of SQL Server over the years Heres a challenge many developers face. Ill whittle it down to a very simple example, but one where the pattern applies to many situations. Suppose you have a stored procedure that receives a single vendor ID and updates the freight for all orders with that vendor id. create procedure dbo. UpdateVendorOrders update Purchasing. PurchaseOrderHeader set Freight Freight 1 where VendorID VendorID Now, suppose we need to run this for a set of vendor IDs. Today we might run it for three vendors, tomorrow for five vendors, the next day for 100 vendors. We want to pass in the vendor IDs. If youve worked with SQL Server, you can probably guess where Im going with this. The big question is how do we pass a variable number of Vendor IDs Or, stated more generally, how do we pass an array, or a table of keys, to a procedure Something along the lines of exec dbo. UpdateVendorOrders SomeListOfVendors Over the years, developers have come up with different methods: Going all the way back to SQL Server 2000, developers might create a comma-separated list of vendor keys, and pass the CSV list as a varchar to the procedure. The procedure would shred the CSV varchar variable into a table variable and then join the PurchaseOrderHeader table to that table variable (to update the Freight for just those vendors in the table). I wrote about this in CoDe Magazine back in early 2005 (code-magazinearticleprint. aspxquickid0503071ampprintmodetrue. Tip 3) In SQL Server 2005, you could actually create an XML string of the vendor IDs, pass the XML string to the procedure, and then use XQUERY to shred the XML as a table variable. I also wrote about this in CoDe Magazine back in 2007 (code-magazinearticleprint. aspxquickid0703041ampprintmodetrue. Tip 12)Also, some developers will populate a temp table ahead of time, and then reference the temp table inside the procedure. All of these certainly work, and developers have had to use these techniques before because for years there was NO WAY to directly pass a table to a SQL Server stored procedure. Until SQL Server 2008 when Microsoft implemented the table type. This FINALLY allowed developers to pass an actual table of rows to a stored procedure. Now, it does require a few steps. We cant just pass any old table to a procedure. It has to be a pre-defined type (a template). So lets suppose we always want to pass a set of integer keys to different procedures. One day it might be a list of vendor keys. Next day it might be a list of customer keys. So we can create a generic table type of keys, one that can be instantiated for customer keys, vendor keys, etc. CREATE TYPE IntKeysTT AS TABLE ( IntKey int NOT NULL ) So Ive created a Table Typecalled IntKeysTT . Its defined to have one column an IntKey. Nowsuppose I want to load it with Vendors who have a Credit Rating of 1..and then take that list of Vendor keys and pass it to a procedure: DECLARE VendorList IntKeysTT INSERT INTO VendorList SELECT BusinessEntityID from Purchasing. Vendor WHERE CreditRating 1 So, I now have a table type variable not just any table variable, but a table type variable (that I populated the same way I would populate a normal table variable). Its in server memory (unless it needs to spill to tempDB) and is therefore private to the connectionprocess. OK, can I pass it to the stored procedure now Well, not yet we need to modify the procedure to receive a table type. Heres the code: create procedure dbo. UpdateVendorOrdersFromTT IntKeysTT IntKeysTT READONLY update Purchasing. PurchaseOrderHeader set Freight Freight 1 FROM Purchasing. PurchaseOrderHeader JOIN IntKeysTT TempVendorList ON PurchaseOrderHeader. VendorID Te mpVendorList. IntKey Notice how the procedure receives the IntKeysTT table type as a Table Type (again, not just a regular table, but a table type). It also receives it as a READONLY parameter. You CANNOT modify the contents of this table type inside the procedure. Usually you wont want to you simply want to read from it. Well, now you can reference the table type as a parameter and then utilize it in the JOIN statement, as you would any other table variable. Så där har du det. A bit of work to set up the table type, but in my view, definitely worth it. Additionally, if you pass values from , youre in luck. You can pass an ADO data table (with the same tablename property as the name of the Table Type) to the procedure. For developers who have had to pass CSV lists, XML strings, etc. to a procedure in the past, this is a huge benefit. Finally I want to talk about another approach people have used over the years. SQL Server Cursors. At the risk of sounding dogmatic, I strongly advise against Cursors, unless there is just no other way. Cursors are expensive operations in the server, For instance, someone might use a cursor approach and implement the solution this way: DECLARE VendorID int DECLARE dbcursor CURSOR FASTFORWARD FOR SELECT BusinessEntityID from Purchasing. Vendor where CreditRating 1 FETCH NEXT FROM dbcursor INTO VendorID WHILE FETCHSTATUS 0 EXEC dbo. UpdateVendorOrders VendorID FETCH NEXT FROM dbcursor INTO VendorID The best thing Ill say about this is that it works. And yes, getting something to work is a milestone. But getting something to work and getting something to work acceptably are two different things. Even if this process only takes 5-10 seconds to run, in those 5-10 seconds the cursor utilizes SQL Server resources quite heavily. Thats not a good idea in a large production environment. Additionally, the more the of rows in the cursor to fetch and the more the number of executions of the procedure, the slower it will be. When I ran both processes (the cursor approach and then the table type approach) against a small sampling of vendors (5 vendors), the processing times where 260 ms and 60 ms, respectively. So the table type approach was roughly 4 times faster. But then when I ran the 2 scenarios against a much larger of vendors (84 vendors), the different was staggering 6701 ms versus 207 ms, respectively. So the table type approach was roughly 32 times faster. Again, the CURSOR approach is definitely the least attractive approach. Even in SQL Server 2005, it would have been better to create a CSV list or an XML string (providing the number of keys could be stored in a scalar variable). But now that there is a Table Type feature in SQL Server 2008, you can achieve the objective with a feature thats more closely modeled to the way developers are thinking specifically, how do we pass a table to a procedure Now we have an answer Hope you find this feature help. Feel free to post a comment. Importing SQL Server Data Using SSIS - Which Option is Fastest By: Daniel Calbimonte Read Comments (27) Related Tips: More Integration Services Development This article is useful for SSIS developers who do not know which tasks are best to use in an SSIS projects. The main problem is that at the end of development if performance is slow then you will need to rebuild the project and change components. This article shows various ways of importing data and shows which types of components perform best within SSIS. The contest will be between the following components: ODBC Tasks ADO NET Tasks OLEDB Task SQL Server Destination T-SQL Tasks I created different SSIS packages in order to test performance. In this demo I used SSIS 2012 and the database Adventureworks 2012 . In this demo I am going to import the table AdventureWorks2012.Sales. SalesOrderDetail to the test2 database which is on the same instance of SQL Server. SalesOrderDetails is the table with more rows in AdventureWorks2012. In order to create the database test2 and the destination table dbo. OrderDetails, use this T-SQL code: Test 1 - ODBC Tasks The first example will use ODBC Source and ODBC Destination as shown below: When we run the package we notice the average time is 5 minutes 57 seconds to import the rows: Test 2 - ADO NET Tasks As noticed, ODBC is pretty slow. Lets try another approach. We are going to truncate the destination table first: Lets try ADO tasks to import the same data and verify if these components are faster: The average elapsed time in my testing was 11 seconds. This is much better. Test 3 - OLEDB Tasks This time we are going to import the same data using the OLEDB Tasks. Again we will truncate the table in the test2 database first. The average elapsed time is 5 seconds. Note that I am using the fast load option with the Table Lock option in the OLE DB Destination Task: If we do not use the fast load option, the average elapsed time was 2 minutes and 21 seconds: OK. The fast load option really improves performance. I will return to that configuration. What about the OLE DB Source. By default I am using the option Table or view in the OLE DB Source as shown below: Lets use a SQL Command instead as shown below. The average elapsed time is 2.85 seconds . Test 4 - SQL Server Destination Now, lets try to use the SQL Destination as the destination instead of OLE DB Destination: The average elapsed time is 2.5 seconds. At this point it is the best option. Test 5 - Execute T-SQL Task Finally, some people think that the best option is to use the Execute T-SQL Task: I am using a simple insert statement to import data from one source to another: The average elapsed time is 1.8 seconds Finally Ive been told that if the query runs inside a stored procedure it is even faster: Lets create a stored procedure: After creating the stored procedure we are going to call it in the Execute T-SQL Task: The average elapsed time is 2.12 seconds . The stored procedures does not improve performance. Lets review the table with the results: You may think the morale of the story is to use the Execute T-SQL Task instead of other SSIS tasks. In this example we were importing data on the same instance, but this will not always be the case. So the morale of the story is that there are many alternatives when creating a SSIS project and we have to carefully study the alternatives in different scenarios. There are great SSIS tools and we do not always use the best options. With each new version of SSIS new tasks are added and performance may be improved with existing tasks. The main changes in SSIS for SQL 2008 and 2012 are related to performance improvements. Next Steps If you are working in a SSIS project make sure you are using the best tasks and also verify if there are other SSIS tasks that can be used in your project. Also make sure you are following the best practices recommended by the experts: Last Update: 7132012 Great read and analysis, but I have one caveat to add. If you need to move a large amount of data, you need to take care of the transaction log growth. This is not a much of a concern using SSIS. For instance, I needed to move 1.3 billion rows (15 columns) and began using TSQL which quickly filled my logs. However, using OLE DB Source and Destination (Bulk Inserts) with fast load, there was little impact to the log file. Thursday, September 20, 2012 - 9:19:12 AM - vinodhkumar Its very useful. great job. Thanks Monday, August 27, 2012 - 10:54:42 AM - Orlando Colamatteo I agree with some others that the testbed is a bit contrived. If youre looking to move data from one table to another on the same instance then SSIS will rarely be a viable option. Some form of T-SQL will almost certainly outperform an SSIS operation. A more realistic scenario is moving data between two disparate data sources. It is surpising how poorly the ODBC Destination performs, especially in light of what Microsoft has publicly said in that they will be moving away from OLE DB interfaces and standardizing on ODBC in future products: In the ODBC Destination I expected Microsoft to implement the loading of data via the bulk load API as they did with the FastLoad option of the OLE DB Destination. On a separate note regarding loading data into MySQL with SSIS: In the past I did some performance tests with the Cherry City OLE DB driver for MySQL and it is horribly slow as it only inserts one row at a time. This is not to mention the fact that it crashed BIDS regularly when developing with it. Given the lack of a benefit I would stick with the tools built into SSIS and avoid the hassle of installing and configuring a third party driver. If youre using SSIS 2005 I would recommend using a Script Component as a Destination and issuing batch-inserts against a connection made using the MySQL ODBC Driver: msdn. microsoften-uslibraryms135939.aspx If youre using SSIS 2008 I would recommend using an ADO NET Destination with the MySQL ODBC Driver. In my tests it was only able to achieve about 240 rowsminute throughput to MySQL which is quite disappointing: msdn. microsoften-uslibrarybb895291(vsql.105).aspx If youre using SSIS 2012 I would recommend using an ODBC Destination with the MySQL ODBC Driver. In my tests it outperformed the ADO NET Destination over 3 to 1 but still only achieved about 800 rowsminute throughput, which was still quite disappointing: msdn. microsoften-uslibraryhh758691(vsql.110).aspx

Comments