RedShift:需要帮助优化子查询 WHERE IN (SELECT *)
RedShift: need helps for optimizations subquery WHERE IN (SELECT *)
我对 RedShift 有下一个查询:
SELECT contributor_user_id,
device_id_source,
device_os,
device_model,
device_design,
device_serial,
device_carrier,
device_os_version,
device_manufacturer,
device_current_app_build,
device_current_app_version
FROM all_values
WHERE all_values.device_id_source :: VARCHAR NOT IN (SELECT device_id_source FROM table WHERE device_id_source IS NOT NULL)
AND all_values.device_os :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_os IS NOT NULL)
AND all_values.device_model :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_model IS NOT NULL)
AND all_values.device_design :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_design IS NOT NULL)
AND all_values.device_serial :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_serial IS NOT NULL)
AND all_values.device_carrier :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_carrier IS NOT NULL)
AND all_values.device_os_version :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_os_version IS NOT NULL)
AND all_values.device_manufacturer :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_manufacturer IS NOT NULL)
AND all_values.device_current_app_build :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_current_app_build IS NOT NULL)
AND all_values.device_current_app_version :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_current_app_version IS NOT NULL)
)
据我所知,WHERE IN (SELECT) 比“JOIN”慢,而且子查询中有很多相同的请求,我认为这不好。但我是 SQL 的新手,我不知道如何用 JOIN 重写上面的代码。能不能帮我科普一下?
谢谢!
“WHERE NOT IN (SELECT ...”可能非常昂贵,因为列表可能很长并且需要进行大量比较才能确定该值是否不在列表中。有点更便宜的方法是使用“WHERE NOT EXISTS (SELECT ...”,它在内部更像是一个 JOIN 结构,但对于您的情况来说仍然不够快。
请注意,这些只是根据您的 SQL 和过去的经验做出的猜测。鉴于查询的其余部分看起来多么简单,这是一个不错的选择。您可能仍想查看查询的 EXPLAIN 计划,看看哪里的成本增加最多。
最好的答案是重新考虑这个查询并删除否定逻辑。如果我没看错,您想找到 contributor_user_id 中的所有行,其中列出的任何列的“table”中对应的列值为 NULL。为此,您正在使用“WHERE NOT IN”执行减法算法。我不知道你的数据模型,所以我不确定这个逻辑是否不正确。
这里的困难是我不知道你的数据和数据模型。该查询将标记“table”中任何列为 NULL 的任何行,但前提是“table”中没有重复 device_os。例如,“table”中的一行 device_model 为 NULL,但另一行中的 device_design 不为 NULL,并且具有相同的 device_os 值将不会被标记。这完全取决于数据中的合法模式。具有相同 device_os 的多行在您的数据中是否合法?
更好的方法是将其变成加法算法,这可能会大大减少获得所需答案所需的工作。不了解数据和所需的逻辑,我不可能提出解决方案。示例数据和预期结果将有助于提出不同的解决方案建议。
我对 RedShift 有下一个查询:
SELECT contributor_user_id,
device_id_source,
device_os,
device_model,
device_design,
device_serial,
device_carrier,
device_os_version,
device_manufacturer,
device_current_app_build,
device_current_app_version
FROM all_values
WHERE all_values.device_id_source :: VARCHAR NOT IN (SELECT device_id_source FROM table WHERE device_id_source IS NOT NULL)
AND all_values.device_os :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_os IS NOT NULL)
AND all_values.device_model :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_model IS NOT NULL)
AND all_values.device_design :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_design IS NOT NULL)
AND all_values.device_serial :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_serial IS NOT NULL)
AND all_values.device_carrier :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_carrier IS NOT NULL)
AND all_values.device_os_version :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_os_version IS NOT NULL)
AND all_values.device_manufacturer :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_manufacturer IS NOT NULL)
AND all_values.device_current_app_build :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_current_app_build IS NOT NULL)
AND all_values.device_current_app_version :: VARCHAR NOT IN (SELECT device_os FROM table WHERE device_current_app_version IS NOT NULL)
)
据我所知,WHERE IN (SELECT) 比“JOIN”慢,而且子查询中有很多相同的请求,我认为这不好。但我是 SQL 的新手,我不知道如何用 JOIN 重写上面的代码。能不能帮我科普一下?
谢谢!
“WHERE NOT IN (SELECT ...”可能非常昂贵,因为列表可能很长并且需要进行大量比较才能确定该值是否不在列表中。有点更便宜的方法是使用“WHERE NOT EXISTS (SELECT ...”,它在内部更像是一个 JOIN 结构,但对于您的情况来说仍然不够快。
请注意,这些只是根据您的 SQL 和过去的经验做出的猜测。鉴于查询的其余部分看起来多么简单,这是一个不错的选择。您可能仍想查看查询的 EXPLAIN 计划,看看哪里的成本增加最多。
最好的答案是重新考虑这个查询并删除否定逻辑。如果我没看错,您想找到 contributor_user_id 中的所有行,其中列出的任何列的“table”中对应的列值为 NULL。为此,您正在使用“WHERE NOT IN”执行减法算法。我不知道你的数据模型,所以我不确定这个逻辑是否不正确。
这里的困难是我不知道你的数据和数据模型。该查询将标记“table”中任何列为 NULL 的任何行,但前提是“table”中没有重复 device_os。例如,“table”中的一行 device_model 为 NULL,但另一行中的 device_design 不为 NULL,并且具有相同的 device_os 值将不会被标记。这完全取决于数据中的合法模式。具有相同 device_os 的多行在您的数据中是否合法?
更好的方法是将其变成加法算法,这可能会大大减少获得所需答案所需的工作。不了解数据和所需的逻辑,我不可能提出解决方案。示例数据和预期结果将有助于提出不同的解决方案建议。