如果您改为运行此查询会发生什么?
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)
现在,这个查询与您编写的原始查询完全相同,但没有连接。为了解决这个查询,数据库通过 ID 和 IS_PARENT 遍历表 CATAT 匹配(有一个索引使得这非常快),一旦一行匹配前两个条件,数据库尝试通过表 CG 上的 C_ID 查找现有记录(再次真的如果您有索引,则速度很快),然后它尝试按 ID 对表 CCSD 执行相同操作。这最后 2 次搜索在我发布的第一个查询中是级联的,但想法是一样的:您的查询运行缓慢,因为正在创建一个笛卡尔积(可能已优化,但仍会导致大量行),而我write 只是按 ID 遍历表(没有合并),这些列中可能已经有索引,这就是它运行速度快的原因。