【问题标题】:Choose right sort key on Amazon Redshift在 Amazon Redshift 上选择正确的排序键
【发布时间】:2019-12-01 11:48:45
【问题描述】:

我正在 Amazon Redshift 上创建一个表,用于每天存储大量数据。

我尝试使用排序键尽可能优化数据库性能。

我们的想法是能够通过对这些数据执行选择查询的 API 为 wep 应用程序提供这些数据。

在使用了多个不同的排序键之后,我根本不相信我使用了正确的排序键。我一定是错过/误解了一些东西......

表定义:

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)

数据上下文:

  1. 存储 10 000 000 到 20 000 000 行/天
  2. 保留2年历史

我已经尝试过的排序键:

  1. 复合排序键(设备、is_free、日期、国家、类别、子类别)
  2. 交错排序键(设备、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

有没有可能让它更快? 选择的排序键是坏的吗? 我可以将日期字段放在交错排序键中吗? (即使我读过这是一个坏主意)

如果您认为 Redshift 没有针对这种情况,您是否有其他数据库建议(我对技术没有限制)?

提前感谢您的帮助:)

【问题讨论】:

  • 如果您正在寻找比几秒钟更快的性能和/或希望通过 Web 应用程序为许多用户提供服务,那么 Redshift 可能不是正确的架构选择。您正在寻找什么最大响应(以秒为单位)以及您期望有多少用户?您还需要考虑如何加载数据? (您将希望您的排序键与加载记录的顺序相匹配,以减少重新排序的需要)
  • @JonScott 感谢您的快速回复。几秒钟就可以了,我只是想知道这是否是由于排序键错误以及是否可以改进:限制是 30 秒,但不是 1800 万,这大约是 1/2 天的数据,但 1/2 年的数据数据
  • 如果我每天增加 10/20 百万行,我担心一年中性能下降很多
  • 数据将插入每组国家/日期/设备:所以我将首先插入 50 000 行,例如 - 01/08/19 - iphone,然后 40 000 行用于 cn - 07 /09/19 - ipad ,...此时,没有订单,但如果更好,我可以执行所有日期为 be 然后为 cn 的所有日期
  • 有多少用户(每 24 小时有多少查询)?

标签: database indexing bigdata amazon-redshift database-performance


【解决方案1】:

Redshift绝对是此类 IMO 查询的正确选择。请参阅下面的示例,在这些示例中,我在一个小型集群上的响应时间只有几百毫秒。

日期或时间戳列通常应该是复合排序键中的第一列。按唯一值数量的降序添加其他列。

避免对您经常添加数据的表使用INTERLEAVED 排序键。

这是一个使用来自 TPC-DS 的 store_sales 表的示例,其规模为 100GB:2.65 亿行。我将ss_sold_date_skss_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

【讨论】:

  • 谢谢@JoeHarris 的回答 :) 很高兴知道:我将尝试使用复合排序键和日期作为第一个位置的时间戳,看看性能是否更好 => 现在不同排序键的组合,我的查询速度始终相同:第一次在 3 秒到 5 秒之间(我尝试了 64 000 000 行)
  • 只要例如5s 对你来说没问题,你没有同时运行多个查询然后 redshift 很好,在 OP 帖子中他们暗示 3-7s 不好,可能会有很多并发使用。 OP 仍然必须考虑加载速度,因此排序键可能是一个问题。
  • 5 秒仅适用于第一次运行。在此之后,我看到所有谓词变体的响应时间一致为 200-300 毫秒。
猜你喜欢
  • 2018-11-05
  • 1970-01-01
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 2019-09-16
  • 1970-01-01
  • 2020-11-25
  • 2015-08-22
相关资源
最近更新 更多