db2 exists 和in联合使用优化方法

本文探讨了在SQL查询中使用exists与in时索引的有效性问题,并通过具体案例对比了不同场景下索引的表现,最后提供了一种有效的SQL优化方案。

  对于exists和in,当exists里面嵌套in的时候,如果in语句里面只有一个元素的情况下,这时候索引是有效的.如果多于一个元素,这种情况下索引会失效.下面写一个简单的例子来验证以上说法.

 

sql1:

select   1 from pm_measurement_recalculation reca
where       
  exists (                      
                    select
                    operating_date
                from
                    PM_MEASUREMENT_READING reading
                where
                    reading.measurement_id in(
                     -- 10000828, 10000670, 10000671,215001368
                   10000828,10000670,10000671
                    )
)

执行计划图:(索引失效)

sql2:

select   1 from pm_measurement_recalculation reca
where       
  exists (                      
                    select
                    operating_date
                from
                    PM_MEASUREMENT_READING reading
                where
                    reading.measurement_id in(
                     -- 10000828, 10000670, 10000671,215001368 
                   10000671
                    )
)

执行计划图:

 

 

 

 

 

 

 

准备优化的原sql:

update
        pm_measurement_recalculation reca
    set
        reca.from_operating_date=(    select
            min(tempTable.operating_date) as operating_date   
        from
            (    select
                min(r.operating_date) as operating_date
            from
                pm_measurement_reading r
            where
                r.measurement_id in (
                   10000828, 10000670, 10000671, 215001368
                ) 
            group by
                r.operating_date   ) as tempTable  )  
        where
            reca.measurement_id in (
                10000828, 10000670, 10000671,215001368
            )
            and
   exists  (
 select operating_date from PM_MEASUREMENT_READING reading
                where reading.measurement_id in(
                                                                            10000828, 10000670, 10000671,215001368
                                                                             ) 
                    )

执行计划图

 

优化后的sql:

update
        pm_measurement_recalculation reca
    set
        reca.from_operating_date=(    select
            min(tempTable.operating_date) as operating_date   
        from
            (    select
                min(r.operating_date) as operating_date
            from
                pm_measurement_reading r
            where
                r.measurement_id in (
                   10000828, 10000670, 10000671, 215001368
                ) 
            group by
                r.operating_date   ) as tempTable  )  
           where
            reca.measurement_id in (
                10000828, 10000670, 10000671,215001368
            )
            and
   exists  (
 select operating_date from PM_MEASUREMENT_READING reading
                where reading.measurement_id in(
                     select
                   reading.measurement_id
                   from
                    PM_MEASUREMENT_READING reading
                where
                    reading.measurement_id in(
                       10000828, 10000670, 10000671,215001368
                    )
                    group by reading.measurement_id
                    fetch first 1 rows only
            ) 
                    )
        执行计划图:

    
         

优化使用 IN EXISTSSQL 查询可以从以下几个方面入手: ### 优先选择合适的操作符 在判断记录存在性时,EXISTS 通常比 IN 更高效,尤其是子查询关联主表字段时。因为 IN 可能导致主查询全表扫描,未利用索引;而 EXISTS 可以通过关联索引实现高效匹配。例如,在判断客户是否有订单时,使用 EXISTS 会更合适: ```sql SELECT * FROM customers WHERE EXISTS (SELECT * FROM orders WHERE orders.customer_id = customers.id); ``` 不过,若子查询结果集极小(如 <100 条),IN 可能更直观且性能相当,但需通过执行计划验证[^1]。 ### 确保索引配合 确保子查询关联字段有索引,否则 EXISTS 可能退化为全表扫描。例如,在上述查询中,`orders` 表的 `customer_id` 字段 `customers` 表的 `id` 字段应该有索引,这样可以加速查询: ```sql -- 为 orders 表的 customer_id 字段创建索引 CREATE INDEX idx_orders_customer_id ON orders (customer_id); -- 为 customers 表的 id 字段创建索引 CREATE INDEX idx_customers_id ON customers (id); ``` ### 避免滥用 NOT IN NOT EXISTS 同理优于 NOT IN,但需注意 NULL 值处理,因为 NOT IN 隐含 NULL 逻辑陷阱。当子查询包含 NULL 时,NOT IN 可能返回空结果集,而 NOT EXISTS 能正确处理 NULL。例如: ```sql -- 危险:当 subquery 包含 NULL 时,NOT IN 可能返回空结果集 SELECT * FROM table1 WHERE col1 NOT IN (SELECT col2 FROM table2); -- 安全:NOT EXISTS 正确处理 NULL SELECT * FROM table1 t1 WHERE NOT EXISTS (SELECT 1 FROM table2 t2 WHERE t2.col2 = t1.col1); ``` ### 利用数据库优化器 现代数据库优化器(如 Oracle、SQL Server、PostgreSQL)会将某些 IN 查询转换为 EXISTS 形式,利用半连接(Semi - Join优化策略。因此,在这些数据库中,有时可以放心使用 IN,让数据库自动进行优化[^2]。 ### 分析执行计划 通过分析 SQL 查询的执行计划,了解查询的执行过程性能瓶颈,从而针对性地进行优化。不同数据库查看执行计划的方法不同,例如在 MySQL 中可以使用 `EXPLAIN` 关键字: ```sql EXPLAIN SELECT * FROM customers WHERE customer_id IN (SELECT customer_id FROM orders); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值