在 Amazon Redshift 上选择正确的排序键
Choose right sort key on Amazon Redshift
我正在 Amazon Redshift 上创建一个 table 用于每天存储大量数据。
我尝试使用排序键尽可能优化数据库性能。
我们的想法是能够通过 API 对其执行 select 查询来使用这些数据为 wep 应用程序提供服务。
在使用了多个不同的排序键之后,我根本不相信我使用的是正确的排序键。我一定是遗漏/误解了什么...
Table 定义:
CREATE TABLE test_table(
date date NOT NULL,
country char(2) NOT NULL,
application_id integer NOT NULL,
device smallint NOT NULL,
category smallint NOT NULL,
subcategory smallint DEFAULT NULL,
rank smallint DEFAULT NULL,
subrank smallint DEFAULT NULL,
is_free smallint NOT NULL,
downloads integer DEFAULT NULL)
distkey(application_id)
数据上下文:
- 每天存储 10 000 000 到 20 000 000 行
- 保留 2 年的历史记录
排序键我已经试过了:
- 复合排序键(设备,is_free,日期,国家,类别,子类别)
- 交错排序键(设备,is_free,国家,类别,子类别)
已执行性能测试(在生成的 1800 万行上):
使用这些排序键中的任何一个,下面的示例查询总是在 3 秒和 7 秒内执行,具体取决于给定国家/类别的数量和日期范围。
查询示例:
SELECT country, category, sum(downloads)
FROM test_table
WHERE country IN ('fr','jp', 'de', 'gb', 'us')
AND category in (6014, 6005, 6011, 6004, 6017)
AND device = 0
AND is_free = 1
AND date >= '2019-01-01' AND date <= '2019-04-01'
GROUP BY country, category;
SELECT category, country, rank, avg(downloads)
FROM test_table
WHERE country IN ('br','co', 'ru')
AND category in (6009, 6008, 6000)
AND device = 1
AND is_free = 0
AND rank IN (1, 10, 100)
AND date BETWEEN '2019-03-01' AND '2019-04-01'
GROUP BY category, country, rank;
SELECT category, country, application_id, sum(downloads)
FROM test_table
WHERE country IN ('us', 'cn', 'jp')
AND category in (6010, 6003, 6002)
AND device = 1
AND is_free = 1
AND date BETWEEN '2019-04-01' AND '2019-06-01'
GROUP BY category, country, application_id
是否可以让它更快?
selected 排序键不好吗?
我可以将日期字段放在交错排序键中吗? (即使我读过这是个坏主意)
如果您认为Redshift不适合这种情况,您有其他数据库建议吗(我对技术没有限制) ?
提前感谢您的帮助:)
Redshift 绝对 IMO 此类查询的正确选择。请参阅下面的示例,其中我在一个微型集群上获得的响应时间仅为几百毫秒。
日期或时间戳列通常应该是复合排序键中的第一列。按唯一值数量的降序添加其他列。
避免对 table 定期添加数据的对象使用 INTERLEAVED
排序键。
这是一个使用 TPC-DS 中的 store_sales
table 在 100GB 规模下的示例:2.65 亿行。我将 ss_sold_date_sk
和 ss_sold_date_sk
代理键转换为真实的时间戳。
-- column | distinct val
-- ss_hdemo_sk | 7,200
-- ss_promo_sk | 1,000
-- ss_store_sk | 201
-- ss_quantity | 100
CREATE TABLE IF NOT EXISTS "store_sales_ts" (…)
DISTSTYLE KEY
DISTKEY ("ss_item_sk")
SORTKEY ("ss_sold_ts"
,"ss_hdemo_sk"
,"ss_promo_sk"
,"ss_store_sk"
,"ss_quantity")
;
计时是在 2 节点 dc2.large
集群上进行的。结果缓存已禁用,如图所示。
SET enable_result_cache_for_session TO off
;
SELECT ss_store_sk
, COUNT(*) AS sales_count
, AVG(ss_quantity) AS avg_quantity
FROM store_sales_ts
WHERE ss_sold_ts BETWEEN '2001-09-01' AND '2001-09-30'
AND ss_store_sk IN (356,241,160,70)
GROUP BY 1
;
--First run: 5415.869 ms
--Second run: 1485.217 ms
--Third run: 173.262 ms
--Change month: 337.084 ms
SELECT ss_quantity
, COUNT(*) AS sales_count
, AVG(ss_ext_discount_amt) AS avg_discount_amt
FROM store_sales_ts
WHERE ss_sold_ts BETWEEN '2001-09-01' AND '2001-09-30'
AND ss_quantity > 90
GROUP BY 1
;
--First run: 5717.890 ms
--Second run: 206.465 ms
--Change year: 210.091 ms
我正在 Amazon Redshift 上创建一个 table 用于每天存储大量数据。
我尝试使用排序键尽可能优化数据库性能。
我们的想法是能够通过 API 对其执行 select 查询来使用这些数据为 wep 应用程序提供服务。
在使用了多个不同的排序键之后,我根本不相信我使用的是正确的排序键。我一定是遗漏/误解了什么...
Table 定义:
CREATE TABLE test_table(
date date NOT NULL,
country char(2) NOT NULL,
application_id integer NOT NULL,
device smallint NOT NULL,
category smallint NOT NULL,
subcategory smallint DEFAULT NULL,
rank smallint DEFAULT NULL,
subrank smallint DEFAULT NULL,
is_free smallint NOT NULL,
downloads integer DEFAULT NULL)
distkey(application_id)
数据上下文:
- 每天存储 10 000 000 到 20 000 000 行
- 保留 2 年的历史记录
排序键我已经试过了:
- 复合排序键(设备,is_free,日期,国家,类别,子类别)
- 交错排序键(设备,is_free,国家,类别,子类别)
已执行性能测试(在生成的 1800 万行上):
使用这些排序键中的任何一个,下面的示例查询总是在 3 秒和 7 秒内执行,具体取决于给定国家/类别的数量和日期范围。
查询示例:
SELECT country, category, sum(downloads)
FROM test_table
WHERE country IN ('fr','jp', 'de', 'gb', 'us')
AND category in (6014, 6005, 6011, 6004, 6017)
AND device = 0
AND is_free = 1
AND date >= '2019-01-01' AND date <= '2019-04-01'
GROUP BY country, category;
SELECT category, country, rank, avg(downloads)
FROM test_table
WHERE country IN ('br','co', 'ru')
AND category in (6009, 6008, 6000)
AND device = 1
AND is_free = 0
AND rank IN (1, 10, 100)
AND date BETWEEN '2019-03-01' AND '2019-04-01'
GROUP BY category, country, rank;
SELECT category, country, application_id, sum(downloads)
FROM test_table
WHERE country IN ('us', 'cn', 'jp')
AND category in (6010, 6003, 6002)
AND device = 1
AND is_free = 1
AND date BETWEEN '2019-04-01' AND '2019-06-01'
GROUP BY category, country, application_id
是否可以让它更快? selected 排序键不好吗? 我可以将日期字段放在交错排序键中吗? (即使我读过这是个坏主意)
如果您认为Redshift不适合这种情况,您有其他数据库建议吗(我对技术没有限制) ?
提前感谢您的帮助:)
Redshift 绝对 IMO 此类查询的正确选择。请参阅下面的示例,其中我在一个微型集群上获得的响应时间仅为几百毫秒。
日期或时间戳列通常应该是复合排序键中的第一列。按唯一值数量的降序添加其他列。
避免对 table 定期添加数据的对象使用 INTERLEAVED
排序键。
这是一个使用 TPC-DS 中的 store_sales
table 在 100GB 规模下的示例:2.65 亿行。我将 ss_sold_date_sk
和 ss_sold_date_sk
代理键转换为真实的时间戳。
-- column | distinct val
-- ss_hdemo_sk | 7,200
-- ss_promo_sk | 1,000
-- ss_store_sk | 201
-- ss_quantity | 100
CREATE TABLE IF NOT EXISTS "store_sales_ts" (…)
DISTSTYLE KEY
DISTKEY ("ss_item_sk")
SORTKEY ("ss_sold_ts"
,"ss_hdemo_sk"
,"ss_promo_sk"
,"ss_store_sk"
,"ss_quantity")
;
计时是在 2 节点 dc2.large
集群上进行的。结果缓存已禁用,如图所示。
SET enable_result_cache_for_session TO off
;
SELECT ss_store_sk
, COUNT(*) AS sales_count
, AVG(ss_quantity) AS avg_quantity
FROM store_sales_ts
WHERE ss_sold_ts BETWEEN '2001-09-01' AND '2001-09-30'
AND ss_store_sk IN (356,241,160,70)
GROUP BY 1
;
--First run: 5415.869 ms
--Second run: 1485.217 ms
--Third run: 173.262 ms
--Change month: 337.084 ms
SELECT ss_quantity
, COUNT(*) AS sales_count
, AVG(ss_ext_discount_amt) AS avg_discount_amt
FROM store_sales_ts
WHERE ss_sold_ts BETWEEN '2001-09-01' AND '2001-09-30'
AND ss_quantity > 90
GROUP BY 1
;
--First run: 5717.890 ms
--Second run: 206.465 ms
--Change year: 210.091 ms