【问题标题】:Filtering a large table by date按日期过滤大表
【发布时间】:2015-07-21 15:47:10
【问题描述】:

我有一个表 VISIT_INFO,其中包含以下列:

pers_key - unique identifyer for each person
pers_name - name of person
visit_date - date at which they visited a business

还有另一个表 VALID_DATES,包含这些列:

condition - string
start_date - date
end_date - date 

我目前有以下查询:

select pers_key, pers_name from VISIT_INFO a
CROSS JOIN
(select start_date, end_date from VALID_DATES where condition = 'condition1') b
WHERE (a.visit_date >= b.start_date and a.visit_date <= b.end_date)
GROUP BY a.pers_key

所以“condition1”有一个特定的 start_date 和 end_date。我需要为两个日期之间的访问过滤 VISIT_INFO。我想知道是否有更有效的方法来做到这一点。根据我目前的理解,它目前必须遍历整个表(数百万行)并将 start_date 和 end_date 添加到每一行。那么它是否必须再次遍历每一行并针对 WHERE 条件进行测试?

我问这个是因为当我删除交叉连接并对条件 1 的 start_date 和 end_date 进行硬编码时,它需要的时间大大减少。我试图避免在日期中进行硬编码,因为它会导致严重的单调乏味。

重申一下,有没有更好的方法可以按 VALID_DATES 中的特定日期过滤 VISIT_INFO?

编辑:我刚刚意识到我遗漏了大量信息,因为这些信息都在 HIVE 中。所以 EXISTS 和 join on(b 和 c 之间的 a)是不可能的。

【问题讨论】:

  • CROSS JOIN 几乎从来都不是正确答案。
  • 你能提供更好的选择吗?

标签: sql performance date join hive


【解决方案1】:

怎么样:

SELECT DISTINCT pers_key, pers_name
FROM visit_info
WHERE EXISTS
(
    SELECT 1
    FROM valid_dates
    WHERE condition = 'condition1'
    AND visit_date BETWEEN start_date AND end_date
);

?

【讨论】:

  • 知道如何在 HIVE 中实现这样的目标吗?我不小心把我使用 hive 的事实从问题主体中排除了。
  • 您运行的是哪个版本的 Hive?从 0.13 开始的 Hive 应该支持 WHERE 子句以及 EXISTS 中的子查询。对于EXISTS,您需要一个相关子查询,但我的示例是相关的。见cwiki.apache.org/confluence/display/Hive/…
  • 我正在运行 .12,这可能就是它给我一个错误的原因。 “无法识别指定函数中“选择”“1”“来自”附近的输入”。 @Tripp 动力学
【解决方案2】:
with dt as (select start_date, end_date from VALID_DATES where condition = 'condition1')
select a.pers_key, a.pers_name 
from VISIT_INFO a
JOIN dt on a.visit_date between dt.start_date and dt.end_date
GROUP BY a.pers_key

【讨论】:

  • 这需要加入 CTE 吗?
  • join dt on a.visit_date between dt.start_date and dt.end_date ?
  • 修改它@JamieD77
【解决方案3】:

尝试exists 版本绝对是可能的。但是,最好扩展VALID_DATES 表,这样每个日期只有一行。

然后,查询:

select vi.*
from VISIT_INFO vi JOIN
     VALID_DATES_expanded vde
     ON vi.visit_date = vde.valid_date
where vde.condition = 'condition1';

可以使用VISIT_INFO(visit_date)VALID_DATES_expanded(condition, valid_date) 上的索引。如果VISIT_INFO 非常大并且查询选择的行相对较少,这可能是解决此问题的最快方法。

【讨论】:

  • 但是这不只是检查 visit_date 是否等于某个日期,而不是检查它是否在两个日期之间?
  • @泰山。 . .扩展表将包含两个值之间的所有日期。尽管数据更大,但等值连接更容易优化。
猜你喜欢
  • 2021-11-23
  • 2020-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-08
相关资源
最近更新 更多