这是一项与市场分割分析相关的工作,我认为每天运行几次。
我将解释的查询类型需要在 10 分钟内完成,涉及最多 5 个表,每个表中有 1000 万条记录。
我是一个sql菜鸟。我将其实现为 Spring 批处理作业,并且需要确定要使用的最有效的 SQL 查询技术。因此,我可以为 AND/OR 条件的任意组合编写动态查询生成代码。
目标是根据多个表中的存在情况来选择 partyId、groupId,这些表更新太频繁,索引变得非常有用。这些表本身是相同的,本质上是由某些现有进程创建的容器。使用日期范围条件,以便选择仅考虑自上次作业运行以来的更改。 (假设日期范围条件有助于查询优化)
因此,对于我的测试用例,我有 5 个表,全部具有以下结构
CREATE TABLE `TABLE1` (
`UPDATED` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`PARTY_ID` varchar(20) NOT NULL,
`GROUP_ID` varchar(20) NOT NULL,
`SEQUENCE_ID` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`SEQUENCE_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=2225551 DEFAULT CHARSET=latin1;
来自 Partition a very large INNER JOIN SQL query 的回答和评论
我拼凑了 2 个可能的查询,一个用于“所有 AND”类型条件,一个用于“所有 OR”类型条件。
select PARTY_ID from
(select distinct PARTY_ID from TABLE1 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00') union all
select distinct PARTY_ID from TABLE2 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00') union all
select distinct PARTY_ID from TABLE3 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00') union all
select distinct PARTY_ID from TABLE4 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00') union all
select distinct PARTY_ID from TABLE5 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00')) as ilv
group by PARTY_ID
having count(*) = 5;
这适用于返回所有表 1-5 中存在的 partyId 的结果集。用户将以 AND/OR 条件的形式提供条件要求,因此这相当于纯粹的 AND 条件集)
select PARTY_ID from
(select distinct PARTY_ID from TABLE1 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00') union all
select distinct PARTY_ID from TABLE2 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00') union all
select distinct PARTY_ID from TABLE3 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00') union all
select distinct PARTY_ID from TABLE4 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00') union all
select distinct PARTY_ID from TABLE5 WHERE (UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00')) as ilv
group by PARTY_ID;
这适用于返回存在表 1-5 中任何一个的 partyId 的结果集。用户将以 AND/OR 条件的形式提供条件要求,因此这相当于纯 OR 条件集)
我需要的是一个示例,说明 AND/OR 条件的组合如何转换为这种类型的查询语法(因为它比标准联接快得多)
例如,正确使用子查询返回 TABLE1 和 TABLE2 和 TABLE3 或 TABLE4 和 TABLE5 中的 party_id 列表,然后我可以看到如何为任何组合编写动态查询生成代码。
我的另一个问题是日期范围实际上有助于提高效率吗? 我还可以有效地使用日期范围来对查询进行分区,以便它可以并行运行吗?
我不确定这一点的原因是我猜测 sql 引擎必须循环遍历每个表的所有行,无论条件是否存在。因此,对查询进行分区可能会导致更多的总循环......这样的推理有意义吗?
最佳答案
如果您只想查询当天的行,那么进行夜间作业是有意义的,该作业在当天的每个表上设置一个新分区(并将前一天的行移动到主分区中)对于每个表)。这样,您每次查询应该只查询数千条记录,而不是数百万条记录。
如果日期/时间范围可能来自任何天,那么在每个表上设置新索引(单独在UPDATED
上)会更有意义或 UPDATED
和 PARTY_ID
的组合。如果您有机会,我建议您尝试针对两组索引尝试更新的查询,并查看它们的比较结果。
实现所需的更复杂功能的一种方法可能是对条件表达式求和 - 例如,如果您希望 TABLE1
和 TABLE2 中包含
和 PARTY_ID
TABLE3
或 TABLE4
和 TABLE5
:
select PARTY_ID from
(select distinct PARTY_ID, 'TABLE1' TABLENAME from TABLE1
WHERE UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00' union all
select distinct PARTY_ID, 'TABLE2' TABLENAME from TABLE2
WHERE UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00' union all
select distinct PARTY_ID, 'TABLE3' TABLENAME from TABLE3
WHERE UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00' union all
select distinct PARTY_ID, 'TABLE4' TABLENAME from TABLE4
WHERE UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00' union all
select distinct PARTY_ID, 'TABLE5' TABLENAME from TABLE5
WHERE UPDATED >= '2015-09-18 14:43:44' AND UPDATED <= '2015-09-18 15:00:00') as ilv
GROUP BY PARTY_ID
HAVING SUM(CASE WHEN TABLENAME IN ('TABLE1','TABLE2','TABLE3') THEN 1 END)=3
OR SUM(CASE WHEN TABLENAME IN ('TABLE4','TABLE5') THEN 1 END)=2;
请注意,等式表达式(在 HAVING
子句中)中的数字需要与 CASE
表达式中检查的表总数相匹配 - 因此查询需要在检查PARTY_ID
是否在前三个表中时检查SUMmed CASE表达式是否等于3,并且需要检查第二个表达式是否等于2 在检查最后两个表时。
关于mysql - 使用sql联合子查询的组合来处理AND/OR条件的组合以进行客户过滤,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32653807/