2012-04-25 17 views
24

Jaki jest najszybszy sposób na eksport plików (obiektów typu blobs) przechowywanych w tabeli programu SQL Server do pliku na dysku twardym? Mam ponad 2,5 TB plików (90 kb avg) przechowywanych jako pliki varbinary i muszę wyodrębnić każdy z nich na lokalny dysk twardy tak szybko jak to możliwe. Wydaje się, że BCP działa, ale zajmie mi to 45 dni z prędkością, jaką widzę, i obawiam się, że mój skrypt w pewnym momencie się nie powiedzie, ponieważ w Management Studio zabraknie pamięci.najszybszy sposób eksportowania obiektów typu blob z tabeli do pojedynczych plików

+1

Jest mało prawdopodobne, aby był to problem z wydajnością BCP. Jak wyglądają twoje wykorzystanie dysków? – RBarryYoung

+0

Średnia długość kolejki dysku jest mniejsza niż jedna dziesiąta sekundy, a średni czas odpowiedzi jest poniżej 5 ms podczas moich testów, co wydaje mi się dobre. W każdym razie wydaje się to rozsądnym osiągnięciem BCP, miałem tylko nadzieję, że może być szybszy sposób. – influent

+0

Może chcesz przeczytać następujące pytanie na DBA.SE: [Optymalizacja wydajności BCP dla danych BLOB] (http://dba.stackexchange.com/questions/5025/optimising-bcp-performance-for-blob-data/). Traktuje przypadek bcp i blob. – Marian

Odpowiedz

28

Próbowałem użyć funkcji CLR i było ponad dwa razy szybsze niż BCP. Oto mój kod.

Oryginalna metoda:

SET @bcpCommand = 'bcp "SELECT blobcolumn FROM blobtable WHERE ID = ' + CAST(@FileID AS VARCHAR(20)) + '" queryout "' + @FileName + '" -T -c' 
EXEC master..xp_cmdshell @bcpCommand 

CLR Metoda:

declare @file varbinary(max) = (select blobcolumn from blobtable WHERE ID = @fileid) 
declare @filepath nvarchar(4000) = N'c:\temp\' + @FileName 
SELECT Master.dbo.WriteToFile(@file, @filepath, 0) 

C# kod dla funkcji CLR

using System; 
using System.Data; 
using System.Data.SqlTypes; 
using System.IO; 
using Microsoft.SqlServer.Server; 

namespace BlobExport 
{ 
    public class Functions 
    { 
     [SqlFunction] 
     public static SqlString WriteToFile(SqlBytes binary, SqlString path, SqlBoolean append) 
     {   
     try 
     { 
      if (!binary.IsNull && !path.IsNull && !append.IsNull) 
      {   
      var dir = Path.GetDirectoryName(path.Value);   
      if (!Directory.Exists(dir))    
       Directory.CreateDirectory(dir);    
       using (var fs = new FileStream(path.Value, append ? FileMode.Append : FileMode.OpenOrCreate)) 
      { 
       byte[] byteArr = binary.Value; 
       for (int i = 0; i < byteArr.Length; i++) 
       { 
        fs.WriteByte(byteArr[i]); 
       }; 
      } 
      return "SUCCESS"; 
      } 
      else 
      "NULL INPUT"; 
     } 
     catch (Exception ex) 
     {   
      return ex.Message; 
     } 
     } 
    } 
} 
+3

Podwajałem wydajność ponownie, używając opcji SET NOCOUNT ON i wysyłając tekst wyniku do tabeli zamiast do okna Wiadomości w systemie SSMS. – influent

+0

Byłoby miło, gdyby T-SQL po prostu zawierało polecenie SELECT z pola MYŚLI W poleceniu DUMPFILE. – Patrick

+1

To robi. Nazywa się BULK INSERT. – Marian

-5

Korzystanie z rozwiązania programującego jest jednym ze sposobów, ale problem z pierwotnym pytaniem, że skrypt może się nie powieść, jeśli SSMS wyczerpie się z pamięci, można również rozwiązać, tworząc zadanie agenta SQL dla tego zadania. To oczywiście całkowicie ignoruje część pytania dotyczącą wydajności.

+1

Proszę podać przykład proponowanego rozwiązania zamiast mówić, jak inne rozwiązania nie będą działać. –

+0

Lub po prostu usuń odpowiedź - odzyska także negatywną reputację poniesione ... –

+0

@PeterB To wszystko w porządku. To wyraźnie pokazuje, jak mentalność stadna dominuje nad SE i że nikt tak naprawdę nie rozumie pierwotnego pytania. Dbać. – ajeh

6

Przybyłem tutaj, szukając eksportu bloba do pliku przy najmniejszym wysiłku. Funkcje CLR nie są czymś, co nazwałbym najmniejszym wysiłkiem. Here opisane Lazier jeden, używając OLE Automation:

declare @init int 
declare @file varbinary(max) = CONVERT(varbinary(max), N'your blob here') 
declare @filepath nvarchar(4000) = N'c:\temp\you file name here.txt' 

EXEC sp_OACreate 'ADODB.Stream', @init OUTPUT; -- An instace created 
EXEC sp_OASetProperty @init, 'Type', 1; 
EXEC sp_OAMethod @init, 'Open'; -- Calling a method 
EXEC sp_OAMethod @init, 'Write', NULL, @file; -- Calling a method 
EXEC sp_OAMethod @init, 'SaveToFile', NULL, @filepath, 2; -- Calling a method 
EXEC sp_OAMethod @init, 'Close'; -- Calling a method 
EXEC sp_OADestroy @init; -- Closed the resources 

Będziesz potencjalnie potrzebne, aby umożliwić uruchamianie procedur przechowywanych na serwerze OA (a następnie go wyłączyć, gdy skończysz):

sp_configure 'show advanced options', 1; 
GO 
RECONFIGURE; 
GO 
sp_configure 'Ole Automation Procedures', 1; 
GO 
RECONFIGURE; 
GO 
+1

Po prostu użyłem tej metody do wygenerowania 979 jpegów z varbinary kolumna identyfikatora zdjęcia identyfikacyjne do dysku sieciowego. Utworzenie obrazów (łącznie 12 MB) trwało około 16 sekund, a 5 minut - napisanie kursora i nieznaczne zmodyfikowanie dostarczonego kodu. Metody innych odpowiedzi zajęłyby znacznie więcej czasu, ale mogą być bardziej efektywne. To podejście było idealne dla moich potrzeb. – ubercam

Powiązane problemy