将表从Amazon RDS导出到CSV文件

vc6uscn9  于 2022-10-31  发布在  Mysql
关注(0)|答案(7)|浏览(351)

我有一个在Amazon RDS中运行的MySQL数据库,我想知道如何将整个表导出为CSV格式。
我目前使用Windows上的MySQL服务器来查询Amazon数据库,但是当我尝试运行导出时,我得到了一个错误,可能是因为没有用于Amazon RDS的专用文件服务器。有解决方案吗?

mbjcgjjk

mbjcgjjk1#

假设您正尝试通过SELECT ... INTO OUTFILE查询从Amazon RDS数据库导出,这确实会产生此常见问题,例如export database to CSV。相应的AWS团队响应证实了您的假设,即缺少服务器访问权限会阻止此类导出,并通过导出 * 建议了替代方法通过在MySQL命令行客户端中选择数据并通过管道将输出重新格式化为CSV*,将数据转换为CSV格式,如下所示:

mysql -u username -p --database=dbname --host=rdshostname --port=rdsport --batch
  -e "select * from yourtable"
  | sed 's/\t/","/g;s/^/"/;s/$/"/;s/\n//g' > yourlocalfilename

用户fpalero提供了一种替代的、据说更简单的方法,如果你事先知道并指定字段的话:

mysql -uroot -ppassword --database=dbtest
  -e "select concat(field1,',',field2,',',field3) FROM tabletest" > tabletest.csv
ds97pgxw

ds97pgxw2#

首先,Steffen的答案在大多数情况下都有效。
我最近遇到了一些更大、更复杂的输出,其中“sed”是不够的,于是我决定提出一个简单的实用程序来完成这一任务。
我构建了一个名为sql2csv的模块,它可以解析MySQL CLI的输出:

$ mysql my_db -e "SELECT * FROM some_mysql_table" 

+----+----------+-------------+---------------------+
| id | some_int | some_str    | some_date           |
+----+----------+-------------+---------------------+
|  1 |       12 | hello world | 2018-12-01 12:23:12 |
|  2 |       15 | hello       | 2018-12-05 12:18:12 |
|  3 |       18 | world       | 2018-12-08 12:17:12 |
+----+----------+-------------+---------------------+

$ mysql my_db -e "SELECT * FROM some_mysql_table" | sql2csv

id,some_int,some_str,some_date
1,12,hello world,2018-12-01 12:23:12
2,15,hello,2018-12-05 12:18:12
3,18,world,2018-12-08 12:17:12

您也可以使用内置CLI:

sql2csv -u root -p "secret" -d my_db --query "SELECT * FROM some_mysql_table;"

1,12,hello world,2018-12-01 12:23:12
2,15,hello,2018-12-05 12:18:12
3,18,world,2018-12-08 12:17:12

有关更多信息,请参阅 sql2csv(GitHub)。

jv2fixgn

jv2fixgn3#

假设在RDS中使用MySQL,另一种选择是使用批处理模式,它输出制表符分隔的值,并转义换行符、制表符和其他特殊字符。我还没有发现一个CSV导入工具不能处理制表符分隔的数据。例如:

$ mysql -h myhost.rds.amazonaws.com -u user -D my_database -p --batch --quick -e "SELECT * FROM my_table" > output.csv

正如Halfgaar所指出的,--quick选项会立即刷新,因此它避免了大型表的内存不足错误。要引用字符串(推荐),您需要在查询中做一些额外的工作:

SELECT id, CONCAT('"', REPLACE(text_column, '"', '""'), '"'), float_column
  FROM my_table

REPLACEtext_column值中的任何双引号字符进行转义。我还建议对日期时间字段使用iso8601字符串,因此:

SELECT CONCAT('"', DATE_FORMAT(datetime_column, '%Y%m%dT%T'), '"') FROM my_table

请注意,如果您有NULL列值,CONCAT将返回NULL.
我已经在一些相当大的表上运行了这个程序,性能相当不错。在与RDS示例相同的VPC中运行MySQL命令时,6亿行和23 GB数据花费了大约30分钟。

xghobddn

xghobddn4#

AWS有一个新的方法来做这件事。只要使用他们的DMS(数据库迁移服务)。
以下是有关如何将表导出到S3存储上的文件的文档:****
您将有可能以两种格式导出:CSVParquet中的一个或多个。

4ngedf3f

4ngedf3f5#

我在EC2上使用Yii框架连接到RDS MySQL。关键是使用fputcsv()。下面的代码在我的本地主机和生产环境中都能很好地工作。

$file = 'path/to/filename.csv';
$export_csv = "SELECT * FROM table";

$qry = Yii::app()->db->createCommand($export_csv)->queryAll();

$fh = fopen($file, "w+");
foreach ($qry as $row) {
    fputcsv($fh, $row, ',' , '"');
}
fclose($fh);
bxjv4tth

bxjv4tth6#

如果你使用Steffen Opel的解决方案,你会注意到它生成了一个包含'concat'字符串文字的头文件。显然这不是你想要的。很可能你想要的是数据的相应头文件。
除了替换列名和表名外,此查询无需任何修改即可运行:

mysql -h xxx.xxx.us-east-2.rds.amazonaws.com 
--database=mydb -u admin -p 
-e "SELECT 'column1','column2' 
UNION ALL SELECT column1,column2 
FROM table_name WHERE condition = value" > dataset.csv

我刚刚在 Numbers OS X应用程序中打开了结果,输出看起来很完美。

nue99wik

nue99wik7#

对于一个非常大的表(~ 500 m行),即使使用--quick,也没有任何内容被写入到我的导出文件中,并且该过程从未完成(+6小时)。我编写了下面的bash脚本来解决这个问题。另一个好处是,在写入每个批处理文件时,您都可以看到进度指示。
只要您有某种顺序列(例如,自动递增的整数PK或日期列),此解决方案就能很好地工作。如果您有大量数据,请确保您的日期列已编制索引!


# !bin/bash

# Maximum number of rows to export/total rows in table, set a bit higher if live data being written

MAX=500000000

# Size of each export batch

STEP=1000000

for (( c=0; c<= $MAX; c = c + $STEP ))
do
   mysql --port 3306 --protocol=TCP -h <rdshostname> -u <username> -p<password> --quick --database=<db> -e "select column1, column2, column3 <table> order by <timestamp> ASC limit $STEP offset $c" | sed 's/\t/","/g;s/^/"/;s/$/"/;s/\n//g' > export$c.csv
done

另一种稍微不同的方法可能会更快,具体取决于您已建立的索引,该方法是按月逐个查看数据:


# !bin/bash

START_YEAR=2000
END_YEAR=2022
for (( YEAR=$START_YEAR; YEAR<=$END_YEAR; YEAR++ ))
do
   for (( MONTH=1; MONTH<=12; MONTH++ ))
   do

      NEXT_MONTH=1
      let NEXT_YEAR=$YEAR+1
      if [ $MONTH -lt 12 ]
      then
         let NEXT_MONTH=$MONTH+1
         NEXT_YEAR=$YEAR
      fi

      mysql --port 3306 --protocol=TCP -h <rdshostname> -u app -p<password> --quick --database=<database> -e "select column1, column2, column3 from <table> where <dateColumn> >= '$YEAR-$MONTH-01 00:00:00' and <dateColumn> < '$NEXT_YEAR-$NEXT_MONTH-01 00:00:00' order by <dateColumn> ASC" | sed 's/\t/","/g;s/^/"/;s/$/"/;s/\n//g' > export-$YEAR-$MONTH-to-$NEXT_YEAR-$NEXT_MONTH.csv
   done
done

希望这能帮助到一些人

相关问题