SQL实战经验 - 运算导致索引失效
· 阅读需 7 分钟
为了获取最近一年内有订单的用户信息,可以使用以下的三种写法去实现,它们在语义上是等价的。那它们的性能如何?如何对它们进行优化?这是本文讨论的问题。
= ANY
)select * from customer where c_custkey in (select o_custkey from orders where O_ORDERDATE>=current_date - interval 1 year)
select * from customer where exists (select * from orders where c_custkey = o_custkey and O_ORDERDATE>=current_date - interval 1 year)
连接消除(Join Elimination)通过在不影响最终结果的情况下从查询中删除表,来简化SQL以提高查询性能。通常,当查询包含主键-外键连接并且查询中仅引用主表的主键列时,可以使用此优化。
考虑下面的例子,
select o.* from orders o inner join customer c on c.c_custkey=o.o_custkey
订单表(orders)和客户表(customer)关联,且c_custkey是客户表的主键,那么客户表可以被消除掉,重写后的SQL如下:
如果使用OR连接两个查询条件,数据库优化器有可能无法使用索引来完成查询。譬如对于以下的SQL语句,
select * from customer where c_phone like '139%' or c_name = 'Ray'
如果这两个字段上都有索引,可以把他们重写为UNION
查询,以便使用索引提升查询性能。
select * from customer where c_phone like '139%'
union
select * from customer where c_name = 'Ray'
但是这种 转换并不总是能够提升查询性能,它需要一定的适用条件,并需要经过基于代价的估算。
表连接的类型主要分为内 连接、外连接(左外、右外、全外)、交叉连接,关于他们的语义可以参考下图。
此图来自文章(Visual Representation of SQL Joins),描述的非常清楚,本文不做太多赘述。