本文整理自:袋鼠雲技術薈 | SQL優化案例(2):OR條件優化html
數棧是雲原生—站式數據中臺PaaS,咱們在github上有一個有趣的開源項目:https://github.com/DTStack/flinkxgit
FlinkX是一個基於Flink的批流統一的數據同步工具,既能夠採集靜態的數據,好比MySQL,HDFS等,也能夠採集實時變化的數據,好比MySQL binlog,Kafka等,是全域、異構、批流一體的數據同步引擎,你們若是有興趣,歡迎來github社區找咱們玩~github
在MySQL中,一樣的查詢條件,若是變換OR在SQL語句中的位置,那麼查詢的結果也會有差別,在較爲複雜的狀況下,可能會帶來索引選擇不佳的性能隱患,爲了不執行效率大幅度降低的問題,咱們能夠適當考慮使用Union all 對查詢邏輯較爲複雜的SQL進行分離。sql
常見OR使用場景,請閱讀如下案例:安全
1. 待優化場景app
執行計劃工具
共返回1 行記錄,花費 5 ms。性能
2. 場景解析測試
從查詢條件中能夠看出 token 和 uid 過濾性都很是好,可是因爲使用了 or, 須要採用 index merge 的方法才能得到比較好的性能。但在實際執行過程當中MySQL優化器默認選擇了使用registrationId 上的索引,致使 SQL 的性能不好。優化
3. 場景優化
咱們將SQL改寫成union all的形式。
共返回5 行記錄,花費 5 ms。
經過對比優化先後的執行計劃,能夠明顯看出,將SQL拆分紅兩個子查詢,再使用union對結果進行合併,穩定性和安全性更好,性能更高。
1. 待優化場景
執行計劃
2. 場景解析
本例的SQL查詢中有一個子查詢,子查詢被當成驅動表,產生了auto_key,經過SQL拆分進行測試,驗證主要是(pc.count =0 , or pc.count is null )會影響到整個SQL的性能,須要進行比較改寫。
3. 場景優化
首先咱們能夠單獨思考(pc.count =0 , or pc.count is null ) 如何進行優化?先寫一個相似的SQL
這個時候咱們看到的實際上是同一個列,但對應不一樣的值,這種狀況能夠利用case when進行轉換。
再回到原始SQL進行改寫。
能夠看出優化後的SQL比原始SQL快了30秒,執行效率提高約50倍。
1. 待優化場景
2.場景解析
咱們仔細分析上述查詢語句,發現雖然業務邏輯只須要查詢半分鐘內修改的數據,但執行過程卻必須對全部的數據進行關聯操做,帶來沒必要要的性能損耗。
3.場景優化
咱們對原始SQL進行拆分操做,第一部分sql-01以下:
sql-01以user_msg 表爲驅動,使用gmt_modified 索引過濾最新數據。
第二部分sql-02以下:
ql-02以user爲驅動表,msg user_id 的索引過濾行很好。
第三部分sql-03以下:
sql-03以group爲驅動表,使用gmt_modified 索引過濾最新數據。
MySQL OR條件優化的常見場景主要有如下狀況:
一、相同列能夠使用IN進行代替
二、不一樣列及複雜的狀況下,能夠使用union all 進行分離
三、關聯SQL OR條件
咱們須要結合實際場景,分析優化。