問題起因:
一個存在很久的一個查詢接口,在做了一次性能優化改動之后,發現查詢結果的排序偶爾出現混亂的情況(客戶現場混亂,本地測試正常)
問題分析:
將客戶現場偶然出現混亂的數據導入本地數據庫,調用該查詢接口,發現這個問題使用該客戶數據必現,直接數據庫使用該接口的SQL語句進行查詢,發現同樣有該問題的存在,斷定是SQL優化導致的該問題
問題解決:
經排查,該接口優化以后開發去掉了order by,想僅通過走索引排序。問題來了,加索引不代表會用索引,數據庫走執行計划是依據統計信息計算算出來的,統計信息是抽樣獲得的,當帶查詢條件的查詢數據使用索引和全表掃描的開銷差不多或者全表掃描的開銷更快的時候,數據庫會直接使用全表掃描的執行計划,不會走索引,全表掃描使用的就是數據庫的默認排序,應該是根據數據塊(索引塊)內記錄的物理順序展示的,所以接口查詢出來的數據不一定符合我們的預期排序結果。
舉例:
下圖Order1表總數據量是109997條,num>0的是109997條,num<40的是75條。

接下來我們可以看一下109997條和75條的執行計划的不同。


可以很清楚的看到select * from Order1 where num>0 的SQL走的全表掃描,select * from Order1 where num<40的SQL走的索引查找
最后這種需要返回排序結果的查詢接口,建議要么再SQL語句后加order by,要么在代碼里面進行排序后返回結果。我們項目目前采取的是第一種方案
PS:
1、索引起不起作用有很多因素,我這個例子里面,數據量是唯一因素,因為其他變量都沒有變化,只有數據量的變化
2、我們本地測試沒有問題是因為剛好做業務產生的數據與物理存儲一致,走數據庫默認排序也沒發現這個問題。
