如果您运行此查询会发生什么?
SELECT COUNT(*) AS ROW_COUNT
FROM CATAT
WHERE CATAT.ID = 1007642
AND CATAT.IS_PARENT = 1
AND EXISTS(SELECT 1 FROM CG WHERE CG.C_ID = CATAT.ID AND EXISTS(SELECT 1 FROM CCSD WHERE CCSD.G_ID = CG.ID))
我相信问题出在你在查询中的双连接中,
希望能帮助到你!
编辑:
在原始查询中详细说明:
SELECT COUNT(*) AS ROW_COUNT
**FROM CATAT, CG, CCSD**
WHERE CATAT.ID = 1007642
AND CG.C_ID = CATAT.ID
AND CATAT.IS_PARENT = 1
AND CCSD.G_ID = CG.ID
第二行是问题,当您在Oracle的from子句中列出其他表时,这意味着您正在编写隐式连接IF,并且仅当您列出并匹配每个表上的所有主键与另一个表上的另一列时.根据您在where子句中添加的主键组件,它将导致常规内部联接(如果您匹配所有主键列),或者它可能导致类似于笛卡尔积的类似于我认为计划的情况你发布了图片,我可以在查询计划中看到合并加入选项笛卡尔.
所有这一切意味着数据库正在生成一个非常大的表,并且该表中的行数是CCSD中的所有行* CG中的所有行* CATAT中的所有行(CCSD有几百万,如您所述,所以这导致您感知到的缓慢),然后尝试遍历此临时表,检查您已有的过滤器.
发生此问题的原因是原始查询未针对任务进行优化,而我发布的查询是.
我所做的是读你查询以了解你想要做什么,你试图列出具有特定ID和IS_PARENT = 1的表CATAT的子集,但你只想列出那些ID的那些(CATAT.ID)在表CG和表CCSD中打开(或存在).在编写查询时,我尝试使用条件中相同的级联,但我最初发布的查询也可以这样写:
SELECT COUNT(*) AS ROW_COUNT
FROM CATAT
WHERE CATAT.ID = 1007642
AND CATAT.IS_PARENT = 1
AND EXISTS(SELECT 1 FROM CG WHERE CG.C_ID = CATAT.ID )
AND EXISTS(SELECT 1 FROM CCSD WHERE CCSD.G_ID = CATAT.ID)
现在,此查询与您编写的原始查询完全相同,但没有连接.为了解决这个问题,数据库遍历IDAT和IS_PARENT匹配的表CATAT(有一个索引使得它真的很快),一旦一行符合前两个条件,数据库试图通过表CG上的C_ID找到现有记录(再次真的如果你有一个索引,则快速),之后它会尝试通过ID对表CCSD执行相同的操作.在我发布的第一个查询中,最后2个搜索是级联的,但是这个想法是相同的:您的查询运行缓慢,因为创建了一个笛卡尔积(可能是优化的,但仍导致大量行)而我的write只是通过ID遍历表(没有合并),这可能已经在这些列中有索引,这就是它运行速度快的原因.