如何在Amazon redshift中编写这个postgres查询,使其像postgres一样优化?

时间:2016-07-06 18:17:38

标签: sql postgresql amazon-redshift

这是我在postgres中使用的原始查询 -

SELECT a.id,
    (SELECT val
       FROM database.detail x
      WHERE name = 'blablah'
        AND x.id = b.id) AS myGroup,
    c.username,
    a.someCode,
    a.timeTaken,
    a.date ::timestamp WITH time ZONE AT time ZONE 'PST' AS date,
    SUM (CASE WHEN (b.name = 'name1') THEN b.val ::INTEGER ELSE 0 END ) AS name11,
    SUM (CASE WHEN (b.name = 'name2') THEN b.val ::INTEGER ELSE 0 END ) AS name12
FROM
    database.myTable a,
    database.detail b,
    database.client c
WHERE
    a.id = b.id
    AND a.c_id = c.c_id
    AND a.date > current_date - interval '2 weeks'
GROUP BY 1, 2, 3, 4, 5, 6

以下是我将此查询转换为亚马逊红移查询的方式。

SELECT a.id,
    b.val AS myGroup,
    c.username,
    a.someCode,
    a.timeTaken,
    convert_timezone('PST', a.date) AS date,
    SUM (CASE WHEN (b.name = 'name1') THEN b.val ::INTEGER ELSE 0 END ) AS name11,
    SUM (CASE WHEN (b.name = 'name2') THEN b.val ::INTEGER ELSE 0 END ) AS name12
FROM
    database.myTable a,
    database.detail b,
    database.client c
WHERE
    a.id = b.id
    AND b.name = 'blablah'
    AND a.c_id = c.c_id
    AND a.date > current_date - interval '2 weeks'
GROUP BY 1, 2, 3, 4, 5, 6 LIMIT 10

CASE语句似乎没有按照预期的方式执行,基本上name11和name12的值都是零。我的postgres查询返回这些的有效值,但redshift查询没有。

此外,此查询非常慢。 Postgres查询需要大约150毫秒,此查询需要2分钟。

我们怎样才能更好地做到这一点?

1 个答案:

答案 0 :(得分:1)

Redshift查询优化来自群集,表格设计,数据加载,数据清理和分析。

让我回答上面列表中的一些核心接触点。 1.确保你的桌子mytable,detail,client有正确的SORT_KEY,DIST_KEY 2.确保连接中的所有桌子都经过分析和真空处理。

以下是以Redshift格式编写的同一SQL的另一个版本。

我做的很少调整

  1. 使用“With Clause”优化群集级别计算
  2. 使用加入正确的方式并确保左/右连接很重要 基于数据。
  3. 使用date_range和子句表进行面向对象的种类。
  4. 在下面的主SQL中使用Group By。
  5. 我的Redshift SQL版本

    /** Date Range Computation **/
    with date_range as (
        select ( current_Date - interval '2 weeks' ) as two_weeks
    ),
    /** Filter main ResultSet**/
    myGroupSet as (
        SELECT b.val AS myGroup,
               c.username,
               a.someCode,
               a.timeTaken,
               (case when (b.name == 'name1') THEN b.val::INTEGER ELSE 0 END ) as name11,
               (case when (b.name == 'name2') THEN b.val::INTEGER ELSE 0 END ) as name12
          FROM database.myTable a,
          join date_range dr on a.date > dr.two_weeks
          join database.detail b on b.id = a.id
          join database.client c on c.c_id = a.c_id
         where a.date > current_Date - interval '2 weeks'
    )
    /** Apply Aggregation **/
    select myGroup, username, someCode, timeTaken, date,
           sum(name1), sum(name2)
      from myGroupSet
      group by myGroup, username, someCode, timeTaken, date