大家好,我是安果!
工作中,我們經(jīng)常需要編寫(xiě) SQL 腳本,對數據庫進(jìn)行增、刪、改、查,很少會(huì )考慮到 Sql 性能優(yōu)化
實(shí)際上,從性能角度考慮,有很多 Sql 關(guān)鍵字都有它們各自的使用場(chǎng)景;如果使用恰當,能大大地提升后端服務(wù)的響應效率
下面以 Mysql 為例,羅列出幾個(gè)比較實(shí)用的小 Tips
union [all] 代表聯(lián)合查詢(xún),即:將多個(gè)查詢(xún)結果合并起來(lái)成一個(gè)結果并返回
PS:union 聯(lián)合查詢(xún)針對每一個(gè)查詢(xún)結果,必須保證列數量、列數據類(lèi)型及查詢(xún)順序一致
語(yǔ)法如下:
# 以?xún)蓮埍淼穆?lián)合查詢(xún)?yōu)槔?/span>
# table_one:表一
# table_two:表二
# 表一中的查詢(xún)字段:table_one_field1,table_one_fileld2...
# 表二種的查詢(xún)字段:table_two_field1,table_two_field2...
# 注意:表一、表二查詢(xún)字段數目、字段類(lèi)型、字段順序應該保持一致
select table_one_field1,table_one_fileld2...
from table_one
union [all]
select table_two_field1,table_two_field2...
from table_two;
其中,union、union all、or 三者的區別如下:
union
表鏈接后會(huì )利用字段的順序進(jìn)行排序,以此篩選掉重復的數據行,最后再返回結果
因此,當數據量很大時(shí)效率很低
union all
相比 union,union all 在表鏈接時(shí)不會(huì )刪除重復的數據行,直接返回表聯(lián)合后的結果
因此,union all 執行效率要高很多,在不需要去重和排序時(shí),更推薦使用 union all
or
or 用于 SQL where 子句中,SQL 腳本可讀性更高,但是它會(huì )引起全表掃描,根本不走索引查詢(xún)
所以通常情況下,union [all] 查詢(xún)會(huì )利用索引進(jìn)行查詢(xún),執行效率要高于 or;但是當 or 條件中查詢(xún)列相同,or 的執行效率要高于 union
group by 分組查詢(xún),根據一個(gè)或多個(gè)列對結果集進(jìn)行分組,一般配合聚合函數使用
語(yǔ)法如下:
# 查詢(xún)字段:多個(gè)查詢(xún)字段
select 查詢(xún)字段...,聚合函數...
from table_one where 條件語(yǔ)句 group by 分組字段...having 分組條件;
# 比如
select red_num1,count(red_num1)
from dlt where create_at>='2021-11-01' group by red_num1;
其中,having 和 where 使用上有下面區別:
where
在 group by 分組前執行,將查詢(xún)結果按照條件過(guò)濾數據
需要注意的是,where 無(wú)法與聚合函數一起使用
having
只能配合 group by 使用,在分組之后執行,用于過(guò)濾滿(mǎn)足條件的組
需要注意的是,分組是一個(gè)耗時(shí)的操作,建議在分組前使用 where 對數據進(jìn)行一次過(guò)濾,然后再進(jìn)行分組
比如,where 搭配 having 一起使用
# 查詢(xún)表dlt
# 首先,使用where通過(guò)時(shí)間過(guò)濾數據
# 然后,使用字段red_num1+group by對數據進(jìn)行分組
# 最后,使用having對分組后的數據再進(jìn)行一次過(guò)濾
select red_num1,count(red_num1)
from dlt where create_at>='2021-10-01' group by red_num1 having count(red_num1)>=2;exists 用于 where 子句中,一般用于判斷子查詢(xún)中是否會(huì )返回數據,如果返回的數據不為空,則為 True,否則為 False
PS:exists 也可以搭配 not 使用,查詢(xún)出不滿(mǎn)足子查詢(xún)語(yǔ)句的數據
語(yǔ)法如下:
-- exists使用
select *
from 表一 where exists(select * from 表二 where 條件判斷語(yǔ)句);
-- not exists使用
select *
from 表一 where not exists(select * from 表二 where 條件判斷語(yǔ)句);
in 同樣用于 where 子句中,篩選出某個(gè)表字段存在于多個(gè)值中的所有數據
關(guān)鍵字 in 常見(jiàn)的 2 種使用方式如下:
-- in 使用
-- 方式一
select *
from 表名 where 字段 in(過(guò)濾字段1,過(guò)濾字段2,過(guò)濾字段3...);
-- 方式二
select *
from 表名1
where 字段1 in (select 字段2 from 表名2 where condition)由于 SQL 做子查詢(xún)最優(yōu)方案是小表驅動(dòng)大表,對于 in 來(lái)說(shuō)是子查詢(xún)表驅動(dòng)外表,當子查詢(xún)表數據少于主表數據時(shí)推薦使用
而 exists 是外表驅動(dòng)子查詢(xún)表,因此當外表數據少于子查詢(xún)表時(shí)更推薦使用
聯(lián)系客服