Impala 查询 - 优化查询以获得给定键的唯一性
Impala query - optimize a query to get the uniques for given key
我正在寻找计算具有特定 pkey 的唯一用户数以及没有该 pkey 的唯一用户数的方法。
这是一个示例 table:
userid | pkey | pvalue
------------------------------
U1 | x | vx
U1 | y | vy
U1 | z | vz
U2 | y | vy
U3 | z | vz
U4 | null | null
我得到了预期的结果,以获取具有 pkey='y' 的唯一用户和那些没有使用此查询但结果很昂贵的用户:
WITH all_rows AS
( SELECT userid,
IF( pkey='y', pval, 'none' ) AS val,
SUM( IF(pkey='y',1,0) ) AS has_key
FROM some_table
GROUP BY userid, val)
SELECT val,
count(distinct(userid)) uniqs
FROM all_rows
WHERE has_key=1
GROUP BY val
UNION ALL
SELECT 'no_key_set' val,
count(distinct(userid)) uniqs
FROM all_rows a1 LEFT ANTI JOIN
all_rows a2 on (a1.userid = a2.userid and a2.has_key=1)
GROUP BY val;
Results:
val | uniqs
--------------------
vy | 2
no_key_set | 2
我想避免使用任何临时 tables,所以有什么更好的方法可以实现这一点?
谢谢!
通过使用 EXPLAIN
,您可以观察到大部分成本花在了过度 GROUP BY
聚合上,而不是在原始查询中使用子查询。
这是一个简单的实现
WITH t1 AS (
SELECT pkey, COUNT(*) AS cnt
FROM table
WHERE pkey IS NOT NULL
GROUP BY pkey
), t2 AS (
SELECT COUNT(DISTINCT userid) AS total_cnt
FROM table
)
SELECT
CONCAT('no_', pkey) AS pkey,
(total_cnt - cnt) AS cnt
FROM t1, t2
UNION ALL
SELECT * FROM t1
t1
每个 pkey
获得 table 唯一用户数
+------+-----+
| pkey | cnt |
+------+-----+
| x | 1 |
| z | 2 |
| y | 2 |
+------+-----+
t2
获取独立用户总数
+-----------+
| total_cnt |
+-----------+
| 4 |
+-----------+
我们可以使用 t2
的结果得到 t1
的补码 table
+------+-----+
| pkey | cnt |
+------+-----+
| no_x | 3 |
| no_z | 2 |
| no_y | 2 |
+------+-----+
两个 table 的最终并集给出了
的结果
+------+-----+
| pkey | cnt |
+------+-----+
| no_x | 3 |
| no_z | 2 |
| no_y | 2 |
| x | 1 |
| z | 2 |
| y | 2 |
+------+-----+
我正在寻找计算具有特定 pkey 的唯一用户数以及没有该 pkey 的唯一用户数的方法。
这是一个示例 table:
userid | pkey | pvalue
------------------------------
U1 | x | vx
U1 | y | vy
U1 | z | vz
U2 | y | vy
U3 | z | vz
U4 | null | null
我得到了预期的结果,以获取具有 pkey='y' 的唯一用户和那些没有使用此查询但结果很昂贵的用户:
WITH all_rows AS
( SELECT userid,
IF( pkey='y', pval, 'none' ) AS val,
SUM( IF(pkey='y',1,0) ) AS has_key
FROM some_table
GROUP BY userid, val)
SELECT val,
count(distinct(userid)) uniqs
FROM all_rows
WHERE has_key=1
GROUP BY val
UNION ALL
SELECT 'no_key_set' val,
count(distinct(userid)) uniqs
FROM all_rows a1 LEFT ANTI JOIN
all_rows a2 on (a1.userid = a2.userid and a2.has_key=1)
GROUP BY val;
Results:
val | uniqs
--------------------
vy | 2
no_key_set | 2
我想避免使用任何临时 tables,所以有什么更好的方法可以实现这一点?
谢谢!
通过使用 EXPLAIN
,您可以观察到大部分成本花在了过度 GROUP BY
聚合上,而不是在原始查询中使用子查询。
这是一个简单的实现
WITH t1 AS (
SELECT pkey, COUNT(*) AS cnt
FROM table
WHERE pkey IS NOT NULL
GROUP BY pkey
), t2 AS (
SELECT COUNT(DISTINCT userid) AS total_cnt
FROM table
)
SELECT
CONCAT('no_', pkey) AS pkey,
(total_cnt - cnt) AS cnt
FROM t1, t2
UNION ALL
SELECT * FROM t1
获得 table 唯一用户数t1
每个 pkey+------+-----+ | pkey | cnt | +------+-----+ | x | 1 | | z | 2 | | y | 2 | +------+-----+
t2
获取独立用户总数+-----------+ | total_cnt | +-----------+ | 4 | +-----------+
我们可以使用
的补码 tablet2
的结果得到t1
+------+-----+ | pkey | cnt | +------+-----+ | no_x | 3 | | no_z | 2 | | no_y | 2 | +------+-----+
两个 table 的最终并集给出了
的结果+------+-----+ | pkey | cnt | +------+-----+ | no_x | 3 | | no_z | 2 | | no_y | 2 | | x | 1 | | z | 2 | | y | 2 | +------+-----+