2013-07-13 46 views
3

我需要將相當大的SQL Server表〜100GB導出到CSV文件。但不是輸出是一個單一的csv文件,理想情況下它應該是多個文件,每個10GB說10個文件。將SQL Server表導出到多個零件文件

我看到BCP有一個batch_size參數,但是仍然將所有數據寫入單個文件?有沒有其他的免費工具可以滿足我的要求?要麼可以以字節或行數指定文件的大小?

對於上下文來說,數據可以與Hive/Hadoop平臺中的其他數據源相結合,所以如果有更好的數據導出方式,我可以提供建議。

+0

您正在使用哪個版本的SQL Server? –

+0

其2012年企業 – Jon

回答

1

我會先導出文件,然後再將它分成外部。假設你正在Windows機器上運行,那裏有幾個可以提供幫助的「免費軟件」工具。有關更多信息,請參閱超級用戶上的this other answer

4

我想你可以結合使用SQL 2012的分頁功能OFFSETFETCH與BCP:

SELECT * 
FROM Table 
ORDER BY ID --Primary Key 
OFFSET 100000001 ROWS 
FETCH NEXT 100000000 ROWS ONLY 
5

BCP的說法batch_size時不控制輸出,很遺憾。

方法我已經做過這類分裂:

1 -簡單,但不可重複:創建一個命令文件(.CMD),其在表格中的特定行範圍內運行一個多BCP秒。這可能需要基於IDENTITY(1,1)的表上的主鍵。

bcp "SELECT * FROM MyTable WHERE Id BETWEEN 0 AND 10000000" queryout … 
bcp "SELECT * FROM MyTable WHERE Id BETWEEN 10000000 AND 20000000" queryout … 

2 -簡單且可重複的,使用了大量的磁盤:BCP出整個表到一個單一的文件,並使用split創建許多新文件,需要在每個給定的字節數(注意:按行分割會是一個更好的主意IMO)。使用'Cygwin'(GnuWin32不再維護)來安裝split和任何其他你想要的工具。

bcp MyDb.MySchema.MyTable out C:\MyFile.csv -T -w 
split -b 10737418240 C:\MyFile.csv C:\MySplitFile_ 

生成以下文件

C:\MySplitFile_aaa 
C:\MySplitFile_aab 
… 

3 -複雜但重複的,要求可能是不安全的T-SQL:使用xp_cmdshell函數來調用BCP一個存儲過程,通過該表迭代裏面。

DECLARE @loop AS INT; 
--Use WHILE to loop as needed-- 
DECLARE @sql AS VARCHAR(MAX); 
--Add code to generate dynamic SQL here-- 
DECLARE @bcp AS VARCHAR(MAX); 
SELECT @bcp='BCP "'[email protected]+'" queryout C:\MyFolder\MyFile_'[email protected]+'.csv'; 

最後請注意:如果您使用的是您的數據的任何NVARCHAR字段,那麼你需要使用-w標誌,並注意輸出將是UTF-16LE。我會強烈建議使用iconv(從'Cygwin'再次)轉換爲UTF-8之前,嘗試在Hadoop中做任何事情。

2

如果您有一個可排序的主鍵字段,您可以找到定義所需行的邊界的鍵,然後使用定義邊界的WHERE來選擇記錄。

它與喬爲#1相似,但您的密鑰不一定是連續的也不是數字。以下是一個簡單示例:

DECLARE @maxrowsperfile AS bigint = 1048576 
DECLARE boundaries CURSOR FOR 
    SELECT the_sortable_key 
    FROM 
    (
     SELECT 
      the_sortable_key 
      , ROW_NUMBER() OVER(ORDER BY the_sortable_key) AS the_row_number 
     FROM the_table 
    ) AS t 
    WHERE the_row_number % @maxrowsperfile = 0 

OPEN boundaries 

DECLARE @lowerbound AS [key type] = [value A] 
DECLARE @upperbound AS [key type] = [value A] 

FETCH NEXT FROM boundaries 
INTO @upperbound 

IF @lowerbound = @upperbound 
    PRINT 'bcp "SELECT * FROM the_table" queryout file -w -T' 
ELSE 
    DECLARE @filecount AS int = 1 
    BEGIN 
     WHILE @@FETCH_STATUS = 0 
     BEGIN 
      PRINT 'bcp "SELECT * FROM the_table WHERE key > ' + CAST(@lowerbound AS varchar) + ' AND key <= ' + CAST(@upperbound AS varchar) + ' queryout file_' + CAST(@filecount AS varchar) + ' -w -T' 
      SET @filecount = @filecount + 1 
      SET @lowerbound = @upperbound 
      FETCH NEXT FROM boundaries 
      INTO @upperbound 
     END 
     PRINT 'bcp "SELECT * FROM table WHERE key > ' + CAST(@lowerbound AS varchar) + ' queryout file_' + CAST(@filecount AS varchar) + ' -w -T' 

    END 
CLOSE boundaries 
DEALLOCATE boundaries 
相關問題