关于 querying-aws-redshift
querying-aws-redshift 用于启用、检查和查询发布到 S3 Tables 的 Redshift 系统表 Apache Iceberg 数据。它支持 Provisioned 集群和 Serverless 命名空间,适合分析历史或高容量监控数据,且查询不会增加运行中集群的负载。
主要功能
- 01启用并验证 S3 Tables 发布
- 02支持 Provisioned 和 Serverless Redshift
- 03通过 Athena 或 Redshift 查询已发布系统表
- 04指导选择性发布与停用
- 05说明权限、加密和表发现
适用场景
- 01分析历史 Redshift 查询和连接数据
- 02构建监控或审计仪表板
- 03将选定的 SYS_* 数据发布到 S3 Tables
- 04通过 Athena 查询已发布系统表
MCP 相关
该技能配合 AWS MCP 服务进行沙箱执行和审计日志记录效果较佳。其命令使用 AWS CLI,也可在已配置 AWS 凭证的环境中运行。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ aws/ agent-toolkit-for-aws --skill querying-aws-redshift安装后在 Claude Code 中输入/querying-aws-redshift确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/example-queries.mdpermissions-setup.mdsecurity.md详细介绍
查询 AWS Redshift 系统表
概述
与 AWS MCP 服务 配合效果最佳,可实现沙盒执行和审计日志记录。以下所有命令均使用 AWS CLI,可在配置了 AWS 凭证的任何环境中运行。请使用 IAM 角色或临时凭证,避免使用长期访问密钥。
Redshift 可以将系统表(如 sys_query_history、sys_query_detail 和 sys_connection_log 等 SYS_* 监控数据)发布到 S3 Tables,作为持续更新的 Apache Iceberg 表。
全文使用的术语:系统表泛指 SYS_* 数据集,每个数据集都与一个已发布的 Iceberg 表一一对应。本技能中提到的 SYS_ 视图,特指你在集群本身查询的集群内实时对象——它是一个视图,与已发布到 S3 Tables 的副本并非同一对象。这既适用于预置集群,也适用于无服务器命名空间。此功能是对现有日志记录 API 的可选扩展。已发布的表为只读,存储在 AWS 托管的 aws-redshift 表存储桶中,可通过任何兼容 Iceberg 的引擎查询,包括 Amazon Athena 和 Amazon Redshift 本身。
分析历史或海量系统表数据时,优先查询 S3 Tables 副本,而非集群内实时 SYS_ 视图,原因如下:
- 集群内的
SYS_视图保留时间有限;S3 Tables 保留的历史数据远超该时限。 - 查询 S3 Tables 不会给运行中的 Redshift 集群增加负载。
- 日志采用 Iceberg 表,因此可以通过任何兼容 Iceberg 的引擎大规模查询,并与其他数据湖数据联接。
决策树
| 用户意图 | 使用本技能? | 替代方案 |
|---|---|---|
| 为集群或命名空间启用 S3 Tables 日志发布 | 是 | — |
| 确认集群/命名空间是否正在发布,或查找其 S3 Tables 命名空间 | 是 | — |
| 查询 Redshift 系统表中的非实时数据 | 是 | — |
| 构建 Redshift 监控和审计的日报/周报/月报仪表板 | 是 | — |
| 有选择地停止 S3 Tables 发布 | 是 | — |
| 从 Redshift 查询已发布的系统表(跨数据库) | 是 | — |
| 从 Athena 查询已发布的系统表 | 是 | — |
检查实时集群中当前的实时 SYS_ 状态 | 否 | 直接查询集群上的 SYS_ 视图 |
| 查询客户表内部的数据 | 否 | 在集群上直接执行 Redshift SQL |
支持的数据源
| 计算类型 | 启用/禁用 API | 状态 API | 粒度选项 |
|---|---|---|---|
| Redshift 预置集群 | redshift enable-logging / redshift disable-logging | redshift describe-logging-status | cluster(默认)、account |
| Redshift 无服务器命名空间 | 使用 --s3-table-action Enable/Disable 的 redshift-serverless update-namespace | redshift-serverless get-namespace | namespace(默认)、account |
两种计算类型都会将数据发布到同一个 AWS 托管的 aws-redshift 表存储桶中,发布后查询方式完全相同。二者仅在启用/禁用 API 和状态响应的大小写上有所不同;请参阅常见任务中的标志和字段表。
本技能不涵盖发送到 S3 或 CloudWatch 的 Redshift 审计日志(useractivitylog、userlog、connectionlog)。这些日志使用 Serverless 上单独的 --log-exports 机制,并非 SYS_* 系统表。
常见任务
1. 检查是否已配置
查询前,请确认集群或命名空间已发布到 S3 Tables。
# Provisioned
aws redshift describe-logging-status --region <REGION> --cluster-identifier <CLUSTER_ID>
# Serverless
aws redshift-serverless get-namespace --region <REGION> --namespace-name <NAMESPACE_NAME>
解读响应。 两种计算类型返回的信息相同,但字段名称和大小写不同——Provisioned 在 S3Tables 下使用 PascalCase,Serverless 在 namespace.s3TablePublishStatus 下使用 camelCase:
| 含义 | Provisioned(describe-logging-status) | Serverless(get-namespace) |
|---|---|---|
| 未启用 | LoggingEnabled: false 或没有 S3Tables 块 | 没有 s3TablePublishStatus 块 |
| 目标包含 S3 Tables | LogDestinationType 包含 s3table | logDestinationType 包含 s3table |
已发布的 SYS_* 表列表 | S3Tables.S3Tables | namespace.s3TablePublishStatus.s3Tables |
| S3 Tables 命名空间的准确名称(查询时必需) | S3Tables.S3TableNamespace | namespace.s3TablePublishStatus.s3TableNamespace |
| 粒度 | S3Tables.S3TableGranularity(cluster/account) | namespace.s3TablePublishStatus.s3TableGranularity(namespace/account) |
| 每张表的最近摄取时间 | S3Tables.LastIngestionTimes | namespace.s3TablePublishStatus.lastIngestionTimes |
| 是否已发布所有可用系统表 | S3Tables.EnabledAll | namespace.s3TablePublishStatus.enabledAll |
注意:
- 存在多个启用的目标时,
LogDestinationType是一个以逗号连接的列表,例如"cloudwatch,s3table"。请使用子串/包含检查,而不是与s3table精确比较。 LastIngestionTimes/lastIngestionTimes映射为空,或某张已列为已发布的表未出现在映射中,表示该表的数据可能仍在传输中。请比较连续的值,确认是否有新数据写入。- 对于 Serverless,此功能不要读取顶层的
logExports字段——该字段包含 CloudWatch/S3 审计日志(useractivitylog、userlog、connectionlog),与SYS_*S3 Tables 发布无关。
2. 启用(如果尚未配置)
# Provisioned
aws redshift enable-logging --region <REGION> --cluster-identifier <CLUSTER_ID> --log-destination-type s3table --log-exports <SYS_TABLE>... --s3-table-granularity <cluster|account> --s3-table-kms-key-id <KMS_KEY_ARN>
# Serverless
aws redshift-serverless update-namespace --region <REGION> --namespace-name <NAMESPACE_NAME> --log-destination-type s3table --s3-table-names <SYS_TABLE>... --s3-table-action Enable --s3-table-granularity <namespace|account> --s3-table-kms-key-id <KMS_KEY_ARN>
--s3-table-kms-key-id 是有意在两个命令中都包含的参数,并非可选项。省略它不会导致失败,但表会回退到 AWS 拥有的密钥,你无法审计该密钥、通过策略限制其使用或撤销它。由于 SYS_* 表包含 query_text、user_name 和 remote_host,请将客户管理的密钥视为默认选项,仅在临时环境中省略该参数。
从 AWS 控制台启用:Amazon Redshift Console > Clusters > 选择你的集群 > Tabs > Integrations / System table integration
对于同一功能,两种计算类型使用不同的参数。 不要将 Provisioned 的参数名称用于 Serverless:
| 用途 | Provisioned(enable-logging) | Serverless(update-namespace) |
|---|---|---|
| 要发布的系统表 | --log-exports | --s3-table-names |
| 启用或禁用 | 分别使用 enable-logging / disable-logging 操作 | --s3-table-action Enable | Disable |
| 粒度 | --s3-table-granularity cluster | account | --s3-table-granularity namespace | account |
| 客户管理的 KMS 密钥 | --s3-table-kms-key-id | --s3-table-kms-key-id |
| 验证但不应用 | --dry-run | --dry-run |
说明:
- 粒度:Provisioned 支持
cluster(默认)或account;Serverless 支持namespace(默认)或account。 cluster/namespace粒度 → 每个集群/命名空间对应一个 S3 表;account→ 每个账户、每个区域的所有集群/命名空间共用一个表。- 使用
all发布所有可用的SYS_*表——Provisioned 使用--log-exports all,Serverless 使用--s3-table-names all。 - 强烈建议在生产环境中启用静态加密。 如果不指定
--s3-table-kms-key-id,发布的表将使用 AWS 拥有的密钥加密,你无法审计该密钥、通过策略限制其使用或撤销它。SYS_*表包含query_text、user_name和remote_host(请参阅安全注意事项),因此请传入客户管理的密钥。请使用${SKILL_DIR}/references/security.md中的完整密钥策略授予密钥访问权限,不要使用简化的操作列表——该策略需要 两个 服务主体(用于发布的systemtables.redshift.amazonaws.com和用于表维护/压缩的maintenance.s3tables.amazonaws.com)。如果只配置发布服务主体,写入会成功,但压缩会悄然失败。 - 两种操作都接受
--dry-run,可在不做任何更改的情况下验证请求。Provisioned 成功时会返回DryRunOperation错误(“Request would have succeeded, but DryRun flag is set”);Serverless 则返回空响应体和退出代码 0。请注意,Serverless 的 dry-run 只验证请求的 结构,不验证参数值,因此 dry-run 成功并不保证这些值会被接受。
选择性禁用:
# Provisioned
aws redshift disable-logging --region <REGION> --cluster-identifier <CLUSTER_ID> --log-destination-type s3table --log-exports <SYS_TABLE>...
# Serverless
aws redshift-serverless update-namespace --region <REGION> --namespace-name <NAMESPACE_NAME> --log-destination-type s3table --s3-table-names <SYS_TABLE>... --s3-table-action Disable
3. 验证权限
两种路径的完整设置命令:${SKILL_DIR}/references/permissions-setup.md。创建角色或注册资源之前,请先加载该文件。
Athena 路径——需要在 Glue 中注册 s3tablescatalog/aws-redshift 目录、具有输出位置的工作组,以及 S3 Tables 读取权限。确认该目录可查询:
aws glue get-databases --region <REGION> \
--catalog-id "<ACCOUNT>:s3tablescatalog/aws-redshift"
返回命名空间 → 已注册且可查询。EntityNotFoundException / CATALOG_NOT_FOUND → 尚未启用 S3 Tables 集成(S3 控制台 > 表存储桶 > 启用集成)。请加密工作组输出位置——Athena 会将完整结果集(包括 query_text 和 user_name)写入 S3。
Redshift 自动挂载路径——需要 Provisioned RA3 集群和四步设置:创建 query_s3_tables 角色(信任策略必须同时指定 redshift.amazonaws.com 和 lakeformation.amazonaws.com,后者需包含 sts:AssumeRole、sts:SetContext、sts:SetSourceIdentity、sts:TagSession 全部四项),将其附加到集群,使用 Lake Formation 注册表存储桶,并将 Redshift 服务相关角色添加到 ReadOnlyAdmins。最常导致失败的限制:
- 两个信任语句都必须以
aws:SourceAccount为条件——裸服务主体存在混淆代理风险。 - **不要将
AWSLakeFormationDataAdmin附加到集群的查询角色。**它仅由执行设置的主体在设置期间使用。集群角色只需要读取权限。 - 自动挂载采用轮询,而非回调——目录最长可能需要 300 秒才会出现在
pg_database中。重启集群可立即触发发现。
4. 确定目标表
命名空间——通过 API 获取,不要自行构造:
- 从
describe-logging-status(Provisioned)读取S3Tables.S3TableNamespace,或从get-namespace(Serverless)读取s3TablePublishStatus.s3TableNamespace,并原样使用。 - 可选的合理性检查:API 返回值通常遵循
<namespace_arn_id>_sys格式(cluster/namespace粒度),或<account>_sys格式(account粒度)。仅用此检查值是否看起来正确——API 响应不可用时,绝不要据此生成命名空间。
表——每个可发布的系统表都一一对应于 aws-redshift 表存储桶中的一张表。不要依据记忆中的列表操作——请按以下顺序在运行时解析:
- 此集群/命名空间已发布的集合——使用上述状态调用返回的
S3Tables.S3Tables(Provisioned)或s3TablePublishStatus.s3Tables(Serverless),例如sys_query_history。这是唯一能权威回答“我现在可以查询什么”的依据。 - 此 API 接受的集合——使用
aws redshift enable-logging help(接受的--log-exports值)或aws redshift-serverless update-namespace help(接受的--s3-table-names值)。 - 各表包含的内容——查阅公开的 Redshift SYS 监控视图参考,其中记录了每个
SYS_*视图及其列。AWS 会随时间添加视图,因此应以文档中的当前列表为准,不要将列表硬编码。
列名和类型来自同一份公开参考,或实时表:
aws glue get-table --region <REGION> \
--catalog-id "<ACCOUNT>:s3tablescatalog/aws-redshift" \
--database-name "<NAMESPACE>" --name "<SYS_TABLE>"
对照公开文档查看已发布的表时,需注意两点:枚举类型列(query_type、status、event)的取值会随时间增加,因此应通过 SELECT DISTINCT 确认,而不要按假定的取值集合进行筛选;已发布的 Iceberg 表还会在前面添加数据仓库标识列(warehouse_name、warehouse_namespace_arn 等),而集群内的 SYS_ 视图不包含这些列——它们可用于区分多个以 account 粒度发布的集群。
5. 查询
从 Athena 查询
查询语法:
"s3tablescatalog/aws-redshift"."<NAMESPACE>"."<SYS_TABLE>"
从 Redshift 查询(自动挂载目录)
设置好自动挂载目录后(参见 ${SKILL_DIR}/references/permissions-setup.md),使用跨数据库表示法进行查询:
"aws-redshift@s3tablescatalog"."<NAMESPACE>".<SYS_TABLE>
从 Redshift 查询(外部架构)
或者,创建一个指向 S3 Tables 目录的外部架构:
CREATE EXTERNAL SCHEMA <schema_name>
FROM DATA CATALOG
DATABASE '<NAMESPACE>'
CATALOG_ID '<ACCOUNT>:s3tablescatalog/aws-redshift'
IAM_ROLE 'arn:aws:iam::<ACCOUNT>:role/query_s3_tables'
REGION '<REGION>';
SELECT * FROM <schema_name>.<SYS_TABLE> LIMIT 10;
限制
- 编写任何 SQL 查询之前,必须运行
describe-logging-status或get-namespace获取命名空间 — 不要手动构造 - 对于 Athena 查询,执行之前必须确认工作组和输出位置
- 时间列的单位是微秒。 除以
1000000.0转换为秒 - 表为只读 — 不支持
INSERT/UPDATE/DELETE - 用户未指定限制时,始终添加
LIMIT;尽可能按start_time/record_time筛选
示例
常见需求的示例 SQL — 最长运行查询、错误分析、连接审计、队列时间趋势、跨表联接 — 位于 ${SKILL_DIR}/references/example-queries.md。以下两条规则适用于所有示例:
- 时间列的单位是微秒。 除以 1,000,000 转换为秒。直接报告
elapsed_time会使时长被高估 10^6 倍。 - 除了任何时间戳谓词外,还要按 Iceberg 分区列(
year/month/day或表自身的分区列)进行筛选,否则引擎会扫描完整历史数据。
路由:Athena、Redshift 还是直接访问 SYS_
| 场景 | 使用方式 |
|---|---|
| 历史/高容量日志分析,不增加集群负载 | 在 S3 Tables 上使用 Athena 或 Redshift |
| 已连接到 Redshift 集群,想要查询 S3 Tables 日志 | Redshift 跨数据库查询或外部架构 |
| 将系统表日志与其他数据湖数据联接 | Athena 或 Redshift Spectrum |
| 集群的实时当前状态 | 在集群上直接查询 SYS_ 视图 |
| 无需访问 Redshift 集群的快速临时查询 | Athena |
关键行为
- 不回填 — 只有启用后记录的事件才会传送到 S3 Tables
- 命名空间来自 API — 始终从
describe-logging-status(S3Tables.S3TableNamespace)或get-namespace(s3TablePublishStatus.s3TableNamespace)读取命名空间;不要手动构造 - 微秒计时 — 所有时长列的单位均为微秒;除以 1000000.0 转换为秒
- 只读 — 无法写入已发布的表
- Provisioned 和 Serverless 均适用 — 使用相同的表存储桶(
aws-redshift),但启用 API 不同 - 支持任何兼容 Iceberg 的引擎 — 可通过 Athena、Redshift 或任何能够读取 Iceberg 的引擎进行查询
故障排除
| 错误 | 原因 | 修复方法 |
|---|---|---|
未找到 aws-redshift 存储桶 | 未启用 S3 Tables 集成或尚未开始日志记录 | 使用 --log-destination-type s3table 运行 enable-logging(Provisioned)或 update-namespace(Serverless) |
Athena 中出现 CATALOG_NOT_FOUND | S3 Tables 尚未在 Glue 中注册 | 启用集成:S3 控制台 > 表存储桶 > 启用集成 |
| 启用后 Athena 表为空 | 数据仍在摄取中 | 检查 LastIngestionTimes(Provisioned)/lastIngestionTimes(Serverless);等待后重新查询 |
命名空间中缺少 SYS_* 表 | 启用时未包含系统表 | 重新运行启用操作并包含该表,或使用 all — --log-exports(Provisioned)、--s3-table-names(Serverless) |
| 命名空间错误/为空 | 命名空间是自行构造的,而非从 API 读取 | 使用描述/获取响应中的命名空间 — S3Tables.S3TableNamespace(Provisioned)或 s3TablePublishStatus.s3TableNamespace(Serverless) |
即使已开启发布,状态响应中仍完全没有 S3Tables / s3TablePublishStatus 字段 | AWS CLI / SDK 版本过旧。该字段会被静默省略,而不是报错,因此看起来与功能已禁用完全相同 | 升级 CLI/SDK,然后重新运行。采取行动前,确认发布功能确实已关闭 — 检查命名空间是否存在于 aws-redshift 表存储桶中,或确认 LogDestinationType 是否包含 s3table |
Serverless 上出现 Unknown options: --log-exports, --log-export-action | 对 update-namespace 使用了 Provisioned 的标志名称 | 使用 --s3-table-names 和 --s3-table-action — 请参阅启用部分中的标志表 |
查询表时出现 AccessDenied | 缺少 s3tables:GetTable 或 GetTableData 权限 | 请参阅 references/security.md |
sys_connection_log 查询结果为空 | 查询身份缺少查看权限 | 使用具有超级用户级访问权限的身份 |
目录未显示在 pg_database 中 | LF 资源未注册,或 SLR 未设为 ReadOnlyAdmins | 完成 references/permissions-setup.md 中的 Lake Formation 步骤,等待 5 分钟或重启 |
| Glue 返回 "Unable to assume role" | 信任策略中缺少 sts:SetContext/sts:SetSourceIdentity,或缺少 AWSLakeFormationDataAdmin | 修复信任策略并附加 AWSLakeFormationDataAdmin |
VerificationStatus: NOT_VERIFIED | Lake Formation 注册后的正常情况 | 如果查询正常,则无需采取任何操作 |
| Redshift 中查询失败并提示 "does not exist" | 目录尚未自动挂载(轮询延迟) | 最多等待 300s 或重启集群 |
安全注意事项
完整策略、密钥策略和检测设置:${SKILL_DIR}/references/security.md。授予访问权限前请阅读。以下要求不可妥协:
- 将 IAM 权限范围限定为 S3 Tables 目录,不要使用通配符。Glue 数据库/表 ARN 嵌套在
s3tablescatalog/aws-redshift下 — 裸用database/*会授予对整个账户的元数据读取权限。lakeformation:GetDataAccess是唯一必须使用"Resource": "*"的操作;请通过aws:ResourceAccountStringEquals条件限制其范围。 - KMS 密钥策略需要两个主体,而非一个:
systemtables.redshift.amazonaws.com(发布者)和maintenance.s3tables.amazonaws.com(压缩任务)。只授权发布者会使写入成功,但压缩会静默失败。 query_text可能包含凭证,不只是架构 — 插值后的 SQL 和CREATE USER ... PASSWORD会原样写入sys_query_history。应将对该表的广泛访问视为可能导致机密泄露的决定;使用 Lake Formation 限制列访问。- 发布操作本身可审计,值得设置告警。
s3tables.amazonaws.com的AccessDenied激增和sys_connection_log中的认证失败次数,是需要设置告警的两个信号;请使用客户管理密钥加密告警主题。
参考文件
${SKILL_DIR} 是包含此 SKILL.md 的目录的绝对路径。按需加载这些文件;不要一次性全部读取。
| 文件 | 涵盖内容 | 加载时机 |
|---|---|---|
${SKILL_DIR}/references/permissions-setup.md | Athena 前提条件和工作组加密;完整的 Redshift 自动挂载流程——IAM 角色信任策略和内联策略、Lake Formation register-resource、put-data-lake-settings、SLR ReadOnlyAdmins 步骤,以及 300s 自动挂载轮询 | 运行任何 IAM 或 Lake Formation 设置之前 |
${SKILL_DIR}/references/example-queries.md | 查询运行时间最长的查询、错误分析、连接审计、队列等待时间趋势,以及跨 sys_* 表联接的 SQL 示例 | 编写针对已发布表的查询时 |
${SKILL_DIR}/references/security.md | 完整的最小权限策略、包含两个服务主体的 KMS 密钥策略、query_text 敏感性、CloudTrail/指标筛选器检测 | 授予访问权限之前,或加固现有设置时 |
其他资源
安全最佳实践:
- Amazon Redshift 安全最佳实践
- S3 Tables 安全性和 S3 Tables 的访问管理
- IAM 安全最佳实践
- Lake Formation 底层数据访问控制——说明为什么
lakeformation:GetDataAccess要求"Resource": "*"