【问题标题】:Redshift ----- Nested Loop Join in the query plan - review the join predicates to avoid Cartesian products -----Redshift ----- 查询计划中的嵌套循环连接 - 查看连接谓词以避免笛卡尔积 -----
【发布时间】:2021-03-28 05:58:43
【问题描述】:

我正在尝试在 redshift 中编写一个查询,该查询在内部连接中有一个“BETWEEN”。在 Redshift 中,我知道这可能非常昂贵,但我想不出另一种写法。似乎我的查询与粘贴的链接完全相同,但在该问题中没有显示答案。有谁知道如何重写此查询以避免笛卡尔积?

Redshift - Simplify Query Plan

select a.ip, a.userid, b.city, b.country, b.ip_start, b.ip_end
from usertable a 
left join ip_table on a.ip between b.ip_start and b.ip_end

在应用数据类型和排序/分布键的情况下,我尝试了多种可能性,但似乎对我的查询没有任何帮助。

  • ip and ip_start/ip_end = bigint
  • 排序键应用于ip_start/ip_endip
  • 分发密钥应用于ipip_start

【问题讨论】:

    标签: sql amazon-redshift amazon-redshift-spectrum


    【解决方案1】:

    您可以使用union all 和窗口函数来获取ip 范围。想法是组合这两个表,然后使用union all 将最近的ip_start 值组合在一起。

    然后您可以通过连接回原始表来引入其他列:

    with ui as (
          select u.user_id, u.ip, null as ip_start
          from usertable u
          union all
          select null, i.ip_start, i.ip_start
          from ip_table i
         )
    select u.*, ip.*
    from (select u.user_id,
                 max(ip_start) over (order by ip) as ip_start
          from ui
         ) ui join
         usertable u
         on u.user_id = ui.user_id join
         ip_table ip
         on ip.ip_start = ui.ip_start;
    

    请注意,这假设范围不重叠,通常是 ip 范围。

    这也不检查ip_end。如果您担心查找表中没有的 IP 地址,您可以这样做。您只需添加 where u.ip <= ip.ip_end 即可将它们过滤掉。

    【讨论】:

    • 您能解释一下您是如何加入查询的后半部分的吗? select u.*, ip.* from (select u.user_id, max(ip_start) over (order by ip) as ip_start from ui) ui join usertable u on u.user_id join ip_table ip on ip.ip_start = ui.ip_start;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 1970-01-01
    • 2017-05-27
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多