今天在写一个业务的时候, 遇到了一个慢查询。
我习惯写业务之前先将sql写好, 这样可以确保写业务之前数据源是对的,并且可以先看到自己写的sql慢不慢,有没有可以优化的地方。 今天在写sql时就遇到了一条很慢的sql.
我最开始写的sql是这样的:
-- 总共1517条结果
SELECT
count(*)
FROM DZShare.T_C_HISDATA_1H H , DZShare.T_C_AI_D A , DZShare.T_Y_SBBHDEVICE_SITE S ,
DZShare.T_C_Item_D I
where H.Pid=A.Pid and A.SubstationId= S.station_id and A.ItemCode=I.ItemCode
这条sql看着 很简单。 H表关联了A表, A表有关联了S表。
但是这条sql查询时确用了一分多钟。
为什么? 有一个注意的地方是, H表的数据量很大!
写sql有个技巧是小表撬大表, 而这条sql 用H这个数据量很大的表撬了其他小表。
我有一次修改了sql 。
修改后的如下:
-- 总共查询出 7498549 条数据
SELECT
count(*)
FROM DZShare.T_C_HISDATA_1H H
LEFT JOIN DZShare.T_C_AI_D A ON H.Pid=A.Pid
LEFT JOIN DZShare.T_Y_SBBHDEVICE_SITE S ON A.SubstationId=S.station_id
LEFT JOIN DZShare.T_C_Item_D I ON A.ItemCode=I.ItemCode
改成这样我才明白, 原来left join 和多表逗号连接 是不同的。
**
多表逗号连接并用where 条件做连接条件, 等价于 inner join 内连接
**
所以正确的修改后的sql应该是:
SELECT
count(*)
FROM
DZShare.T_Y_SBBHDEVICE_SITE S
inner join DZShare.T_C_AI_D A on A.SubstationId=S.station_id
inner join DZShare.T_C_Item_D I ON A.ItemCode=I.ItemCode
inner join DZShare.T_C_HISDATA_1H H ON H.Pid=A.Pid
这条语句想对于前面第一条, 变化是数据量很大的表H被放到了后面, 数据量小的表S被放到了前面。
这样满足了小表撬大表的条件, 查询速度也变快了。