索引對性能方面總是扮演着一個重要的角色,實際上,查詢優化器首先檢查謂詞上的統計資訊,然後才決定用什麼索引。一般情況下,預設會在建立索引時,索引列上均建立統計資訊。但是不代表在非索引鍵上的統計資訊對性能沒有用。
如果表上的所有列都有索引,那麼将會是資料庫負擔不起,同時也不是一個好想法,包括謂詞中用到的所有列加索引同樣也不是好方法。因為索引會帶來負載。因為需要空間存放索引,且每個DML語句都會需要更新索引。
一般來說,建議在where或者ON子句中出現的列上添加索引,但是由于某些情況,很難在所有的謂詞上都建立索引,此時建立統計資訊會是一個最起碼的改進。如果Auto_Create_Statistics為ON,那麼優化器會幫你做這一步。
預設情況下,Auto_Create_Statistics在資料庫級别是設為ON的,但是為了下面需要這裡先改成OFF:
然後建立一個新表用于本文使用:
1、 對于新表,現在是沒有統計資訊在上面的,可以使下面語句來驗證:
因為沒有統計資訊,是以這個查詢是沒有資料的。
2、 現在在新表上建立一個聚集索引:
3、 再次運作步驟一的腳本,可以看到已經有了資料,現在來執行下面的語句,并開啟執行計劃:
4、 下面截圖是步驟3中的執行計劃,關注一下SalesOrdDemo表上有聚集索引掃描,這是合理的,因為沒有WHERE子句在使用SalesOrderID列。而SalesOrderDetails表有非聚集索引掃描。還可以看到實際行數和估計行數有很大差異。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuEjZyY2M2czYxUTMkRDO3QTN0gTMzMzM4IWNyUTOwYWYfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
5、 現在是時候在新表的DueDate上建立統計資訊,因為在查詢中這個列并不包含在索引裡面。
6、 再次執行步驟3的腳本,不需要任何改動:
7、 對比上面的執行計劃,此時在SalesOrderDetails表上已經從非聚集索引掃描變成了聚集索引查找,且開銷隻有2%,更總要的是實際行數和預估行數相差無幾:
如果優化器可以獲得謂詞上列的統計資訊,那麼相會知道将要傳回的行數,并且幫助優化器選擇最佳的執行方式。