改进 Netezza SQL 在 WHERE 子句中包含数百个字符串的查询
Improve Netezza SQL Query That Contains Hundreds of Strings in WHERE Clause
我有一个 Netezza 查询,其中包含数百个潜在字符串的 WHERE 子句。我很惊讶它能运行,但它需要时间才能完成并且偶尔会出错 ('transaction rolled back by client')。这是我查询的伪代码版本。
SELECT
TO_CHAR(X.I_TS, 'YYYY-MM-DD') AS DATE,
X.I_SRC_NM AS CHANNEL,
X.I_CD AS CODE,
COUNT(DISTINCT CASE WHEN X.I_FLG = 1 THEN X.UID ELSE NULL) AS WIDGETS
FROM
(SELECT
A.I_TS,
A.I_SRC_NM,
A.I_CD,
B.UID,
B.I_FLG
FROM
SCHEMA.DATABASE.TABLE_A A
LEFT JOIN SCHEMA.DATABASE.TABLE_B B ON A.UID = B.UID
WHERE
A.I_TS BETWEEN '2017-01-01' AND '2017-01-15'
AND B.TAB_CODE IN ('00AV', '00BX', '00C2', '00DJ'...
...
...
...
...
...
...
...)
) X
GROUP BY
X.I_TS,
X.I_SRC_NM,
X.I_CD
;
在我的查询中,我将 B.TAB_CODE
的结果限制为大约 1,200 个值(超过 10k)。老实说,我很惊讶它能正常工作,但大部分时间都是这样。
有没有更有效的方法来处理这个问题?
如果IN
子句太麻烦,您可以分多个部分进行查询。创建一个包含 TAB_CODE 集的临时 table,然后在 JOIN
.
中使用它
WITH tab_codes(tab_code) AS (
SELECT '00AV'
UNION ALL
SELECT '00BX'
--- etc ---
)
SELECT
TO_CHAR(X.I_TS, 'YYYY-MM-DD') AS DATE,
X.I_SRC_NM AS CHANNEL,
--- etc ---
INNER JOIN tab_codes Q ON B.TAB_CODES = Q.tab_code
如果您想进一步提高性能,请考虑使用真正的临时 table (CTAS
)
如果我猜对了,X.I_TS 实际上是一个“时间戳”,因此我希望它每天包含许多不同的值。你能证实吗?
如果我是对的,查询可能会受益于将“group by X.I._TS,...”更改为“group by 1,...”
此外,'Count(Distinct Case...' 永远不会 return 除了 1 或 NULL 之外的任何其他值。你能确认吗?
如果我是对的,您可以通过将其更改为“MAX(Case...”
来摆脱昂贵的“DISTINCT”
可以关注我吗:)
我们已经看到 "cheaper" 将原始 table CTAS 到另一个,根据您的主要条件分发,然后查询 table 的情况。
我有一个 Netezza 查询,其中包含数百个潜在字符串的 WHERE 子句。我很惊讶它能运行,但它需要时间才能完成并且偶尔会出错 ('transaction rolled back by client')。这是我查询的伪代码版本。
SELECT
TO_CHAR(X.I_TS, 'YYYY-MM-DD') AS DATE,
X.I_SRC_NM AS CHANNEL,
X.I_CD AS CODE,
COUNT(DISTINCT CASE WHEN X.I_FLG = 1 THEN X.UID ELSE NULL) AS WIDGETS
FROM
(SELECT
A.I_TS,
A.I_SRC_NM,
A.I_CD,
B.UID,
B.I_FLG
FROM
SCHEMA.DATABASE.TABLE_A A
LEFT JOIN SCHEMA.DATABASE.TABLE_B B ON A.UID = B.UID
WHERE
A.I_TS BETWEEN '2017-01-01' AND '2017-01-15'
AND B.TAB_CODE IN ('00AV', '00BX', '00C2', '00DJ'...
...
...
...
...
...
...
...)
) X
GROUP BY
X.I_TS,
X.I_SRC_NM,
X.I_CD
;
在我的查询中,我将 B.TAB_CODE
的结果限制为大约 1,200 个值(超过 10k)。老实说,我很惊讶它能正常工作,但大部分时间都是这样。
有没有更有效的方法来处理这个问题?
如果IN
子句太麻烦,您可以分多个部分进行查询。创建一个包含 TAB_CODE 集的临时 table,然后在 JOIN
.
WITH tab_codes(tab_code) AS (
SELECT '00AV'
UNION ALL
SELECT '00BX'
--- etc ---
)
SELECT
TO_CHAR(X.I_TS, 'YYYY-MM-DD') AS DATE,
X.I_SRC_NM AS CHANNEL,
--- etc ---
INNER JOIN tab_codes Q ON B.TAB_CODES = Q.tab_code
如果您想进一步提高性能,请考虑使用真正的临时 table (CTAS
)
如果我猜对了,X.I_TS 实际上是一个“时间戳”,因此我希望它每天包含许多不同的值。你能证实吗? 如果我是对的,查询可能会受益于将“group by X.I._TS,...”更改为“group by 1,...”
此外,'Count(Distinct Case...' 永远不会 return 除了 1 或 NULL 之外的任何其他值。你能确认吗? 如果我是对的,您可以通过将其更改为“MAX(Case...”
来摆脱昂贵的“DISTINCT”
可以关注我吗:)
我们已经看到 "cheaper" 将原始 table CTAS 到另一个,根据您的主要条件分发,然后查询 table 的情况。