2013-07-13 49 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 
相关问题