在Data-Science-on-AWS项目中实现从Athena到Redshift的TSV数据加载
概述
在数据科学项目中,高效的数据加载和转换是关键环节。本文将详细介绍如何利用AWS生态系统中的Athena和Redshift服务,实现TSV格式数据的无缝加载和查询。我们将重点讨论如何通过Redshift Spectrum直接查询S3中的数据,以及如何将数据从S3/Athena高效加载到Redshift数据仓库中。
技术架构
整个流程涉及以下几个核心AWS服务:
- Amazon S3:存储原始TSV格式的客户评论数据
- Athena:提供无服务器查询能力,通过Glue Data Catalog管理元数据
- Redshift:作为数据仓库存储高频访问的数据
- Redshift Spectrum:扩展Redshift的查询能力,使其能直接查询S3中的数据
准备工作
在开始数据加载前,我们需要完成以下准备工作:
import boto3
import sagemaker
# 获取AWS区域信息
session = boto3.session.Session()
region_name = session.region_name
# 获取SageMaker会话和默认S3存储桶
sagemaker_session = sagemaker.Session()
bucket = sagemaker_session.default_bucket()
# 初始化Redshift和Secrets Manager客户端
redshift = boto3.client('redshift')
secretsmanager = boto3.client('secretsmanager')
获取Redshift凭据
安全地获取Redshift集群的访问凭据:
import json
secret = secretsmanager.get_secret_value(SecretId='dsoaws_redshift_login')
cred = json.loads(secret['SecretString'])
master_user_name = cred[0]['username']
master_user_pw = cred[1]['password']
配置参数
设置Redshift和Athena的相关参数:
redshift_cluster_identifier = 'dsoaws'
database_name_redshift = 'dsoaws'
database_name_athena = 'dsoaws'
redshift_port = '5439'
schema_redshift = 'redshift'
schema_athena = 'athena'
table_name_tsv = 'amazon_reviews_tsv'
等待Redshift集群就绪
确保Redshift集群处于可用状态:
import time
response = redshift.describe_clusters(ClusterIdentifier=redshift_cluster_identifier)
cluster_status = response['Clusters'][0]['ClusterStatus']
print(cluster_status)
while cluster_status != 'available':
time.sleep(10)
response = redshift.describe_clusters(ClusterIdentifier=redshift_cluster_identifier)
cluster_status = response['Clusters'][0]['ClusterStatus']
print(cluster_status)
建立Redshift连接
使用AWS Wrangler库建立与Redshift的连接:
import awswrangler as wr
con_redshift = wr.data_api.redshift.connect(
cluster_id=redshift_cluster_identifier,
database=database_name_redshift,
db_user=master_user_name,
)
Redshift Spectrum集成
什么是Redshift Spectrum?
Redshift Spectrum是Amazon Redshift的一项功能,允许直接在S3上执行查询,使用与Redshift相同的SQL语法。它特别适合以下场景:
- 查询存储在S3中的海量数据而无需加载到Redshift
- 执行跨Redshift本地表和S3外部表的联合查询
注册Athena数据库
将Athena数据库注册到Redshift Spectrum,以便通过Glue Data Catalog访问S3数据:
statement = """
CREATE EXTERNAL SCHEMA IF NOT EXISTS {} FROM DATA CATALOG
DATABASE '{}'
IAM_ROLE '{}'
REGION '{}'
CREATE EXTERNAL DATABASE IF NOT EXISTS
""".format(schema_athena, database_name_athena, iam_role, region_name)
wr.data_api.redshift.read_sql_query(
sql=statement,
con=con_redshift,
)
执行示例查询
通过Redshift Spectrum查询S3中的数据:
statement = """
SELECT product_category, COUNT(star_rating) AS count_star_rating
FROM {}.{}
GROUP BY product_category
ORDER BY count_star_rating DESC
""".format(schema_athena, table_name_tsv)
df = wr.data_api.redshift.read_sql_query(
sql=statement,
con=con_redshift,
)
df.head()
将TSV数据加载到Redshift
创建Redshift表结构
在Redshift中创建目标表,考虑以下优化策略:
- 排序键(SORTKEY):选择
product_category
作为排序键,优化基于该列的查询性能 - 分布键(DISTKEY):选择
product_id
作为分布键,因其具有高基数且分布均匀
def create_redshift_table_tsv(wr, con_redshift, table_name_prefix, start_year, end_year):
for year in range(start_year, end_year + 1, 1):
current_table_name = table_name_prefix+'_'+str(year)
statement = """
CREATE TABLE IF NOT EXISTS redshift.{}(
marketplace varchar(2),
customer_id varchar(8),
review_id varchar(14),
product_id varchar(10) DISTKEY,
product_parent varchar(9),
product_title varchar(400),
product_category varchar(24) SORTKEY,
star_rating int,
helpful_votes int,
total_votes int,
vine varchar(1),
verified_purchase varchar(1),
review_headline varchar(128),
review_body varchar(65535),
review_date varchar(10),
year int)
""".format(current_table_name)
wr.data_api.redshift.read_sql_query(
sql=statement,
con=con_redshift,
)
print("Done.")
执行数据加载
使用INSERT INTO...SELECT
语句从Athena表加载数据到Redshift:
def insert_into_redshift_table_tsv(wr, con_redshift, table_name_prefix, start_year, end_year):
for year in range(start_year, end_year + 1, 1):
print(year)
current_table_name = table_name_prefix+'_'+str(year)
statement = """
INSERT
INTO
redshift.{}
SELECT
marketplace,
customer_id,
review_id,
product_id,
product_parent,
product_title,
product_category,
star_rating,
helpful_votes,
total_votes,
vine,
verified_purchase,
review_headline,
review_body,
review_date,
CAST(DATE_PART_YEAR(TO_DATE(review_date, 'YYYY-MM-DD')) AS INTEGER) AS year
FROM
athena.amazon_reviews_tsv
WHERE
year = {}
""".format(current_table_name, year)
wr.data_api.redshift.read_sql_query(
sql=statement,
con=con_redshift,
)
print("Done.")
性能优化建议
- 时间序列表设计:考虑按时间分区创建表,便于数据保留策略的实施
- 批量加载:对于大规模数据加载,优先使用
COPY
命令而非INSERT
- 定期维护:对频繁更新的表执行
VACUUM
和ANALYZE
操作 - 查询优化:利用EXPLAIN分析查询计划,识别性能瓶颈
总结
通过本文介绍的方法,我们实现了从Athena到Redshift的高效数据加载流程。关键点包括:
- 利用Redshift Spectrum直接查询S3数据,减少数据移动
- 合理设计Redshift表的分布键和排序键,优化查询性能
- 使用
INSERT INTO...SELECT
模式实现数据转换和加载的一体化 - 采用时间序列表设计简化数据生命周期管理
这种架构特别适合需要同时处理热数据(Redshift)和冷数据(S3)的分析场景,在性能和成本之间取得了良好平衡。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考