在 OceanBase 數據庫運維中,最讓人頭疼的場景莫過於:一條看似普通的業務 SQL,突然執行超時,前端直接報錯,而你盯着 SQL 和執行計劃,一時找不到突破口。
問題描述
最近技術部門就處理了一起典型案例:應用側反饋某核心業務 SQL 執行 900s 仍無結果,前端應用直接報查詢超時。經過排查與優化,最終將執行時間壓縮至 2-5s,效率提升超 180 倍!今天就帶大家覆盤整個排查過程。
具體執行計劃如下:
問題分析
- 最內層是兩個表進行hash join,走的全表掃描,走hash 是沒問題(可以檢查一下是否關聯字段是否有索引,因數據量不大,當時直接跳過)
- 將第一步的結果集與A做hash關聯時,A表走的全表掃描且數據量過億(110683882),懷疑這裏有問題。
- 查看提供的SQL裏有in的半連接,如下圖
in是把外部表a裏的每行中的aaz661字段拿到 in裏的select 語句中做判斷,外部有多少行就需要判斷多少次,這裏查看in 的SQL語句select aaz661 from xxxxxxxxxx.acs9 where baz002 = '19588674715',發現走索引且耗時1s以內返回一行記錄,如下圖
4.將這一條SQL語句的結果單獨放到in裏,整體SQL執行耗時1-2s
到這裏進一步懷疑半連接in這裏有問題,嘗試做等價改寫
5.半連接in改join
執行計劃沒有變,效率沒有提升
6.半連接in改exists
結果依然失望,執行計劃未變,效率無提升
7.嘗試讓A與SICP4_TREATMENTCENTER_EINP.acs9生成內聯視圖
這樣改寫後發現生產環境執行計劃沒有變,效率沒有提升,執行第8步嘗試強制生效。
8.強制A與SICP4_TREATMENTCENTER_EINP.acs9生成內聯視圖
整體時間由900s縮短到2-5s,執行計劃如下
問題結論
優化器沒有選擇最優的執行計劃,需要人工指定最優訪問路徑。
解決方法
強制A與SICP4_TREATMENTCENTER_EINP.acs9生成內聯視圖,方法如下圖no_merge
整體時間由900s縮短到2-5s。
OceanBase 數據庫中優化不僅要懂 SQL 語法、執行計劃,更要理解優化器的 “思考邏輯”。當常規改寫無效時,不必死磕等價替換,適當的人工干預(如 Hint)的往往能快速破局。
如果你的業務中也遇到過類似的 SQL 性能問題,歡迎在評論區分享你的排查思路,下次見!