這一篇再說(shuō)下索引的最后一個(gè)主題,索引覆蓋,當(dāng)然學(xué)習(xí)比較好的捷徑是看看那些大師們?cè)O(shè)計(jì)的索引,看從中能提取些什么營(yíng)養(yǎng)的東西,下面我們看
看數(shù)據(jù)庫(kù)中一個(gè)核心的Orders表。
一:查看表的架構(gòu)
<1> 先查看這個(gè)表的大概架構(gòu)信息
1 --查看表的架構(gòu)信息2 SELECT c.column_id,c.name,t.name FROM sys.columns AS c 3 JOIN sys.types t4 ON c.system_type_id=t.system_type_id5 WHERE c.object_id=object_id('O_Orders') 6 ORDER BY c.column_id
從這個(gè)訂單表來(lái)看大概有89個(gè)字段。。。還是蠻多的,可能有太多的歷史原因吧,下面就有一個(gè)疑問(wèn)來(lái)了,針對(duì)這么多的字段加上五花八門的類型,如何規(guī)劃
好單列索引和復(fù)合索引。。。下面我們來(lái)看看這些專家們?cè)趺丛O(shè)計(jì)的。
<2> 復(fù)合索引
首先聲明一下,由于我的權(quán)限有限,不能進(jìn)行DBCC IND,PAGE等命令,所以我沒(méi)有能力判斷下面的索引是include索引還是復(fù)合索引,所以這里統(tǒng)一叫成
復(fù)合索引吧。
1 SELECT name,type_desc FROM sys.indexes WHERE object_id=object_id('O_Orders')
從上面可以看到,有9個(gè)非聚集索引,1個(gè)聚集索引,然后可以通過(guò)SHOW_STATISTICS 抽查幾個(gè)索引看看到底關(guān)聯(lián)了哪些字段,找到其中的二個(gè)索引,
覆蓋多達(dá)6列,如索引"idx_order_status_2","IX_O_OrdersUID"。
DBCC SHOW_STATISTICS(O_Orders,idx_order_status_2)DBCC SHOW_STATISTICS(O_Orders,IX_O_OrdersUID)
從這兩個(gè)索引中關(guān)聯(lián)的字段大概可以看出兩點(diǎn)信息:
①:這些字段都比較小,為char(1),smallint,bit這樣的,自然表示的狀態(tài)會(huì)比較少。
②:將表中多個(gè)狀態(tài)少的字段挑選幾個(gè)按照訪問(wèn)頻率組合在一起做一個(gè)索引。
但是仔細(xì)想想,雖然原則上說(shuō)狀態(tài)少的字段不合適建索引,但是類似“訂單狀態(tài)(OrderStatus”這種字段,肯定是一個(gè)被頻繁查詢的列。。。既然是頻繁的列,
肯定就要想辦法優(yōu)化,方法就是建復(fù)合索引,這樣在復(fù)雜的sql中更加容易被撞上索引覆蓋。
比如下面這樣:
1 SET STATISTICS IO ON 2 SELECT OrderStatus, PRocessStatus, SendTicketCity, FlightAgency, Eticket, OrderID3 FROM dbo.Orders WHERE OrderStatus='P' AND ProcessStatus='1' AND SendTicketCity=1
然后繼續(xù)挑選幾個(gè)索引瞄一瞄。。。一般來(lái)說(shuō),覆蓋1到2個(gè)列的索引都叫小索引。
1 DBCC SHOW_STATISTICS(O_Orders,idx_eid_orderdate)2 DBCC SHOW_STATISTICS(O_Orders,IX_O_Order_FinishDate)
通過(guò)上面的索引大概可以看到,Eid和FinishDate這兩列,一眼掃過(guò)就知道應(yīng)該是一個(gè)唯一性比較高的列了,至于為什么要覆蓋2列,那這個(gè)就是根據(jù)業(yè)務(wù)
和生產(chǎn)的滾動(dòng)數(shù)據(jù)來(lái)決定了,那這樣的索引有什么好處呢?同樣更容易會(huì)撞到索引鏈接,也就是多條件中會(huì)走到多個(gè)索引,每個(gè)索引中貢獻(xiàn)一些列剛好可以
滿足select中的所有列。。。比如下面這樣。
1 -- 可以看到,select中的所有列都是有idx_eid_orderdate 和 IX_O_Order_FinishDate 貢獻(xiàn)2 SELECT OrderID,FinishDate,PrepayType,Eid,OrderDate3 FROM dbo.O_Orders WHERE Eid='cctv1' AND FinishDate>2015-1-1
好了,就像園友說(shuō)的,索引就是拆東墻補(bǔ)西墻,每建一個(gè)索引都需要評(píng)估它的利弊。
新聞熱點(diǎn)
疑難解答
圖片精選