2012-04-25 7 views
24

SQL Serverテーブルに格納されたファイル(blob)をハードドライブ上のファイルにエクスポートする最も速い方法は何ですか?私はvarbinaryとして2.5TB以上のファイル(90kb avg)を格納しており、できるだけ早くローカルハードドライブにそれぞれを抽出する必要があります。 BCPは動作しているように見えますが、私が見ている速度では45日以上かかるので、Management Studioのメモリが不足するため、スクリプトの実行に失敗することが心配です。テーブルからブロブを個々のファイルに最も速くエクスポートする方法

+1

これは、BCPのパフォーマンス上の問題ではありません。この間にディスクの利用状況はどのように見えるのですか? – RBarryYoung

+0

平均ディスク待ち行列の長さは10分の1秒以下で、テスト中は平均応答時間が5ミリ秒以下です。とにかくBCPの合理的なパフォーマンスのように思えますが、もっと速い方法があると思っていました。 – influent

+0

DBA.SEの[BLOBデータのBCPパフォーマンスの最適化](http://dba.stackexchange.com/questions/5025/optimising-bcp-performance-for-blob-data/)に関する次の質問をお読みになりたい場合があります。 bcpとblobの大文字と小文字を区別します。 – Marian

答えて

28

CLR機能を使用しようとしましたが、それはBCPの2倍以上でした。ここに私のコードです。

オリジナルメソッド

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

CLR方法

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#コードの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

SET NOCOUNT ONを使用し、SSMSのMessagesウィンドウではなくテーブルに結果テキストを送信することで、パフォーマンスを2倍にしました。 – influent

+0

T-SQLが単にMySQLのSELECTフィールドINTO DUMPFILEコマンドを持っていればいいですね。 – Patrick

+1

です。これは、BULK INSERTと呼ばれています。 – Marian

-5

プログラミングソリューションを使用することも一方の方法ですが、SSMSのメモリが不足した場合にスクリプトが失敗するという問題の元の問題は、タスクのSQLエージェントジョブを作成することによって対処することもできます。これはもちろん、質問のパフォーマンス部分を完全に無視します。

+1

他のソリューションがどのように機能しないかを示す代わりに、提案されたソリューションの例を挙げてください。 –

+0

また、回答を削除するだけで負の評判を取り戻すことができます ... –

+0

@PeterB大丈夫です。これは、牛の精神がSEをどのように支配し、元の質問を誰も本当に理解できないことを明確に示しています。世話をする。 – ajeh

6

ここでは、最小限の労力でBLOBをファイルにエクスポートする方法を探しました。 CLR関数は、私が最小の努力と呼ぶものではありません。 Hereは、OLEオートメーションを使用して、lazier 1を説明した:

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 

(完了したら、それをオフにする)あなたが潜在的にサーバにOAのストアドプロシージャを実行できるようにする必要があります:

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

IDバッジの写真のvarbinary列から979個のjpegをネットワークドライブに生成するためにこのメソッドを使用しました。画像を生成するのに約16秒(合計12MB)を要し、カーソルを書き、提供されたコードをわずかに変更するのに5分かかりました。他の答えの方法ははるかに長いだろうが、より効率的かもしれない。このアプローチは私のニーズに完璧でした。 – ubercam