我对SQL比较陌生。我有一个过去非常快速运行的脚本(<0.5秒),但如果我添加一个更改,则运行速度非常慢(> 120秒) - 我无法理解为什么这种变化会产生如此大的影响。任何帮助都将非常感激!
这是脚本,如果我不包含“tt2.bulk_cnt,它会快速运行 “第26行:
with bulksum1 as
(
select t1.membercode,
t1.schemecode,
t1.transdate
from mina_raw2 t1
where t1.transactiontype in ('RSP','SP','UNTV','ASTR','CN','TVIN','UCON','TRAS')
group by t1.membercode,
t1.schemecode,
t1.transdate
),
bulksum2 as
(
select t1.schemecode,
t1.transdate,
count(*) as bulk_cnt
from bulksum1 t1
group by t1.schemecode,
t1.transdate
having count(*) >= 10
),
results as
(
select t1.*, tt2.bulk_cnt
from mina_raw2 t1
inner join bulksum2 tt2
on t1.schemecode = tt2.schemecode and t1.transdate = tt2.transdate
where t1.transactiontype in ('RSP','SP','UNTV','ASTR','CN','TVIN','UCON','TRAS')
)
select * from results
编辑:我为之前没有提供足够的细节而道歉 - 尽管我可以使用基本的SQL代码,但对于数据库来说,我是一个完整的新手。
数据库:Oracle(我不确定是哪个版本,对不起)
执行计划:
快速查询:
Plan hash value: 1712123489
---------------------------------------------
| Id | Operation | Name |
---------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | HASH JOIN | |
| 2 | VIEW | |
| 3 | FILTER | |
| 4 | HASH GROUP BY | |
| 5 | VIEW | VM_NWVW_0 |
| 6 | HASH GROUP BY | |
| 7 | TABLE ACCESS FULL| MINA_RAW2 |
| 8 | TABLE ACCESS FULL | MINA_RAW2 |
---------------------------------------------
慢速查询:
Plan hash value: 1298175315
--------------------------------------------
| Id | Operation | Name |
--------------------------------------------
| 0 | SELECT STATEMENT | |
| 1 | FILTER | |
| 2 | HASH GROUP BY | |
| 3 | HASH JOIN | |
| 4 | VIEW | VM_NWVW_0 |
| 5 | HASH GROUP BY | |
| 6 | TABLE ACCESS FULL| MINA_RAW2 |
| 7 | TABLE ACCESS FULL | MINA_RAW2 |
--------------------------------------------
答案 0 :(得分:0)
我设法删除了一个不必要的子查询,但distinct
内count
的这种语法在PostgreSQL之外可能不起作用,或者可能不是所需的结果。我知道我当然在那里使用它。
select t1.*, tt2.bulk_cnt
from mina_raw2 t1
inner join (select t2.schemecode,
t2.transdate,
count(DISTINCT membercode) as bulk_cnt
from mina_raw2 t2
where t2.transactiontype in ('RSP','SP','UNTV','ASTR','CN','TVIN','UCON','TRAS')
group by t2.schemecode,
t2.transdate
having count(DISTINCT membercode) >= 10) tt2
on t1.schemecode = tt2.schemecode and t1.transdate = tt2.transdate
where t1.transactiontype in ('RSP','SP','UNTV','ASTR','CN','TVIN','UCON','TRAS')
当您使用这些with
查询时,而不是在您不需要时查询子查询时,您可以将查询优化程序放在膝盖上。
答案 1 :(得分:0)
一些观察,然后做一些事情:
1)需要更多信息。特别是,MINA_RAW2
表中有多少行,此表中存在哪些索引,以及最后一次分析时是什么时候?要确定这些问题的答案,请运行:
SELECT COUNT(*) FROM MINA_RAW2;
SELECT TABLE_NAME, LAST_ANALYZED, NUM_ROWS
FROM USER_TABLES
WHERE TABLE_NAME = 'MINA_RAW2';
从查看计划输出看起来数据库在MINA_RAW2上进行了两次全面扫描 - 如果可以将其减少到不超过一个,那将会很好,希望没有。如果没有关于表中数据的非常详细的信息,总是很难说,但乍一看似乎TRANSACTIONTYPE上的索引可能会有所帮助。如果这样的索引不存在,您可能需要考虑添加它。
2)假设统计数据已过时(自上次分析以来,已添加,删除或更新了旧的,不存在或大量数据(> 10%))运行以下内容:
BEGIN
DBMS_STATS.GATHER_TABLE_STATS(owner => 'YOUR-SCHEMA-NAME',
table_name => 'MINA_RAW2');
END;
将上面的“YOUR-SCHEMA-NAME”替换为正确的架构名称。请记住将架构名称大写!如果您不知道您是否应该收集统计数据,请谨慎行事并做到这一点。它不应该花费太多时间。
3)更新表统计信息后重新尝试现有查询。我认为在数据库中拥有最新统计数据可以解决您的问题。如果不是:
4)此查询正在对GROUP BY的结果执行GROUP BY。这似乎没有必要,因为初始GROUP BY没有进行任何分组 - 相反,似乎这样做是为了获得MEMBERCODE,SCHEMECODE和TRANSDATE的唯一组合,以便按计划和日期可以确定。我认为整个查询可以简化为:
WITH cteWORKING_TRANS AS (SELECT *
FROM MINA_RAW2
WHERE TRANSACTIONTYPE IN ('RSP','SP','UNTV',
'ASTR','CN','TVIN',
'UCON','TRAS')),
cteBULKSUM AS (SELECT a.SCHEMECODE,
a.TRANSDATE,
COUNT(*) AS BULK_CNT
FROM (SELECT DISTINCT MEMBERCODE,
SCHEMECODE,
TRANSDATE
FROM cteWORKING_TRANS) a
GROUP BY a.SCHEMECODE,
a.TRANSDATE)
SELECT t.*, b.BULK_CNT
FROM cteWORKING_TRANS t
INNER JOIN cteBULKSUM b
ON b.SCHEMECODE = t.SCHEMECODE AND
b.TRANSDATE = t.TRANSDATE