将数据从SQL Server加载到S3作为镶木地板 - AWS EMR

时间:2018-02-02 19:11:20

标签: hadoop amazon-s3 hive sqoop parquet

我们目前在SQL Server中有我们的数据,我们正在尝试将它们作为镶木地板文件移动到我们的s3存储桶中。目的是在AWS EMR(主要是Spark,Hive& Presto)中分析这个s3数据。我们不想将数据存储在HDFS中。

  1. 这里有什么选择?据我们所知,我们似乎可以使用spark或sqoop进行导入。虽然在这种情况下,由于并行性(并行数据库连接),sqoop比Spark更快,但似乎无法从sqoop到s3编写镶木地板文件 - Sqoop + S3 + Parquet results in Wrong FS error。解决方法是转到hdfs然后转到s3。然而,这似乎是无效的。如何使用SparkSQL从SQL Server中提取这些数据并在s3中写为镶木地板?

  2. 我们将此数据以此格式加载为实木复合地板

    s3://mybucket/table_a/day_1/(parquet files 1 ... n).
    s3://mybucket/table_a/day_2/(parquet files 1 ... n).
    s3://mybucket/table_a/day_3/(parquet files 1 ... n).
    
  3. 如何将它们组合在一起作为单个表并使用Hive进行查询。我知道我们可以创建指向s3的hive外部表,但是我们可以指向多个文件吗?

    感谢。

    编辑:根据要求添加。

    org.apache.hive.service.cli.HiveSQLException:处理语句时出错:FAILED:执行错误,从org.apache.hive.service上的org.apache.hadoop.hive.ql.exec.DDLTask返回代码1位于org.apache.hive.service.cli.operation的org.apache.hive.service.cli.operation.SQLOperation.runQuery(SQLOperation.java:257)中的.cli.operation.Operation.toSQLException(Operation.java:380) .xOperation.access $ 800(SQLOperation.java:91)at org.apache.hive.service.cli.operation.SQLOperation $ BackgroundWork $ 1.run(SQLOperation.java:348)at java.security.AccessController.doPrivileged(Native Method)位于org.apache.ive.Inc.上的org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1698)的javax.security.auth.Subject.doAs(Subject.java:422)上的org.apache.hive.service.cli.operation.SQLOperation java.util.concurrent.Executors上的$ BackgroundWork.run(SQLOperation.java:362)java中的java.util.concurrent.FutureTask.run(FutureTask.java:266)中的$ RunnableAdapter.call(Executors.java:511)。 util.concurrent.ThreadPoolExecutor java.util.ThreadPoolExecutor中的.runWorker(ThreadPoolExecutor.java:1149)java.lang.Thread.run(Thread.java:748)中的$ Worker.run(ThreadPoolExecutor.java:624)

4 个答案:

答案 0 :(得分:2)

Spark读取jdbc使用mutliple连接拉取数据。这是链接

def
jdbc(url: String, table: String, columnName: String, lowerBound: Long, upperBound: Long, numPartitions: Int, connectionProperties: Properties): 

Construct a DataFrame representing the database table accessible via JDBC URL url named table. Partitions of the table will be retrieved in parallel based on the parameters passed to this function.

Don't create too many partitions in parallel on a large cluster; otherwise Spark might crash your external database systems.

url
JDBC database url of the form jdbc:subprotocol:subname.

table
Name of the table in the external database.

columnName
the name of a column of integral type that will be used for partitioning.

lowerBound
the minimum value of columnName used to decide partition stride.

upperBound
the maximum value of columnName used to decide partition stride.

numPartitions
the number of partitions. This, along with lowerBound (inclusive), upperBound (exclusive), form partition strides for generated WHERE clause expressions used to split the column columnName evenly. When the input is less than 1, the number is set to 1.

connectionProperties
JDBC database connection arguments, a list of arbitrary string tag/value. Normally at least a "user" and "password" property should be included. "fetchsize" can be used to control the number of rows per fetch.DataFrame

https://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.sql.DataFrameReader

<强> http://spark.apache.org/docs/latest/sql-programming-guide.html#jdbc-to-other-databases

创建包含分区列的hive表作为日期并保存并指定以下位置

create table table_name (
  id                int,
  dtDontQuery       string,
  name              string
)
partitioned by (date string) Location s3://s3://mybucket/table_name/

在数据中添加一个名为date的列,并使用sysdate填充它。如果不需要,您无需添加列,我们可以填充该位置。但它也可以作为分析的审核列。 使用spark dataframe.partitionBy(date).write.parquet.location(s3://mybucket/table_name/)

每天执行MSCK repair on the hive table因此,新分区将添加到表格中。

在非数字列上应用numPartitions是通过将该列的哈希函数创建为所需的连接数并使用该列

答案 1 :(得分:2)

虽然我迟到了,但是为了将来的参考。在我们的项目中,我们正是这样做的,我更喜欢Sqoop而不是Spark。

原因:我使用Glue从Mysql读取数据到S3并且读取不是并行的(有AWS支持查看它以及Glue(使用Pyspark)如何工作但是一旦读取就写入S3完成其并行)。这样效率不高而且速度慢。要读取和写入S3的100GB数据需要1.5小时。

所以我在EMR上启用了Sqoop并启用了Glue目录(所以hive Metatore在AWS上)我可以直接从Sqoop写入S3,这样可以更快地将100GB的数据读取需要20分钟。

您必须设置set hive.metastore.warehouse.dir = s3://并且如果您执行hive-import或直接写入,您应该会看到正在写入S3的数据。

答案 2 :(得分:1)

Spark是一个非常好的实用工具。您可以轻松connect to a JDBC data source,并且可以通过指定凭据和S3路径(例如Pyspark Save dataframe to S3)来写入S3。

如果您正在使用AWS,那么Spark,Presto和Hive的最佳选择是使用AWS Glue Metastore。这是一个数据目录,它将您的s3对象注册为数据库中的表,并提供用于查找这些对象的API。

你的Q2的答案是肯定的,你可以有一个引用多个文件的表。如果您有分区数据,通常需要这样做。

答案 3 :(得分:0)

您可以按如下方式创建配置单元外部表

create external table table_a (
 siteid                    string,
 nodeid                    string,
 aggregation_type          string
 )
 PARTITIONED BY (day string)
 STORED AS PARQUET
 LOCATION 's3://mybucket/table_a';

然后,您可以运行以下命令将每天目录下存储的分区文件注册到HiveMatastore

 MSCK REPAIR TABLE table_a;

现在您可以通过配置单元查询访问您的文件了。我们在项目中使用了这种方法并且运行良好。完成上述命令后,您可以运行查询

 select * from table_a where day='day_1';

希望这有帮助。

-Ravi