???? 一般來說,對于做B/S架構的朋友來說,更有機會遇到高并發的數據庫訪問情況,因為現在WEB的普及速度就像火箭升空,同時就會因為高訪問量帶來一系列性能問題,而數據庫一直是用戶與商人之間交流的重要平臺.用戶是沒有耐心忍受一個查詢需要用上10秒以上的,或者更少些,如果經常出現服務器死機或者是報查詢超時,我想那將是失敗的項目。做了幾年的WEB工作,不才,一直沒有遇到過大訪問量或者是海量數據的情況.這里并不是說沒有海量數據的項目就不是好項目,要看項目的應用場合.
?
???? 最近做項目時,偶然得到了這個機會,在我工作過程中,本人發現的單表最大記錄數高達9位數.像訂單表什么的也有8位數.在查詢訂單的時候往往不能通過單表查詢就能解決,還要和其它相關表進行關聯查詢.如此關聯的表數據不大還好,一旦發生大表關聯大表,在查詢時就有可能出現慢長的等待。
?
??? 第一篇:如何盡量避免大表關聯.
??? 第二篇:對大表進行分區.
??? 背景: 有兩張表:
?????? 1:訂單表:記錄用戶訂單的詳細信息. order ,其中有一個會員卡號字段 cardNo ,訂單產生時間.
?????? 2:會員表:記錄會員相關信息. member ,一個會員有一個代理號: proxyID ,代理下面有許多的會員卡: cardNo ,它們共用一個代理號.
?????? 兩表通過cardNo來相關聯.
?
???
需求:
查詢一個用戶或者某些用戶某一時間段所有會員卡產生的訂單情況.
?
? ? 實現SQL:
??????? select 字段 from order
??????????? inner join member on????????????? order.cardNo=member.cardNo
??????????????? and member.proxyID in('a-01',代理號二)
???????????????? and 時間 between '20080101' and '20080131'
?
??
???
解決方案一:
利用
表變量
來替換大表關聯,表變量的作用域為一個批處理,批處理完了,表變量也會隨之失效,比起臨時表有它獨特的優點:不用手動去刪除表變量以釋放內存。
?? declare @t table
?? (cardNo int)
?? insert @t
???? select cardNo from member where in('a-01',代理號二)
?? select 字段 from order
??????????? inner join @t on
????????????? order.cardNo=@t.cardNo and 時間 between '20080101' and '20080131'
??? 這里我就不貼性能比較圖了,有興趣的朋友可以自己嘗試下.這種方法在查詢人員比較多的時候特別有幫助.它要開發員根據實際情況詳細比較,結果并不是統一的,不同的環境結果可能不一樣.希望大家理解.
?
??
解決方案二:
利用索引視圖來提高大表關聯的性能.
?
??
可行性:
一般在大表關聯時,我們的輸出列都遠小于兩表的字段合,像上面的member表只用到了其中的兩個字段(cardNo,proxyID).設想一下,此時的member表如果只有這兩個字段情況會不會好些呢?答案不言而喻.
?
的產生都是實時的,即當調用視圖時,自動擴展視圖,去運行里面相應的select語句.后來才知道在2000后的版本中視圖分一般視圖和索引視圖,一般視圖就是沒有創建索引的我印象中的視圖.而創建了視圖后就稱為索引視圖.索引視圖是物理存在的,可在視圖上首先創建一個唯一的聚集索引,其它字段上也可創建非聚集索引.在不改變基礎表的情況下,起到了優化的效果.
?
?? CREATE VIEW memberViewWITH SCHEMABINDING
AS
??? SELECT cardNo,proxyID from member
GO
--以會員卡號創建一個唯一聚集索引
CREATE UNIQUE CLUSTERED INDEX ix_member_cardNo
??? ON member (cardNo);
GO
? ??
注意:創建索引視圖要點:
? ? ? ? ? ? 1: CREATE VIEW memberView后面要跟上WITH SCHEMABINDING
? ? ? ? ? ? ? ? ? 理由:? 使用 schemaname.objectname 明確識別視圖所引用的所有對象,而不管是哪個用戶訪問該視圖。
?
?????????????????????????? ? 不會以導致視圖定義非法或強制 SQL Server 在該視圖上重新創建索引的方式,更改視圖定義中所引用的對象。
?
??????????? 2:視圖上的第一個索引必須為 CLUSTERED 和 UNIQUE。
????????????????? 理由:必須為 UNIQUE 以便在維護索引視圖期間,輕松地按鍵值查找視圖中的記錄,并阻止創建帶有重復項目的視圖(要求維護特殊的邏輯)。必須為 CLUSTERED,因為只有聚集索引才能在強制唯一性的同時存儲行。
??????????? 3:以下情況可考慮創建索引視圖:
? ? ? ? ? ? ?? ? 可預先計算聚合并將其保存在索引中,從而在查詢執行時,最小化高成本的計算。
?
?????????????? ? 可預先聯接各個表并保存最終獲得的數據集。
?
?????????????? ? 可保存聯接或聚合的組合。
? ? ? ? ? ?? 4:基礎表的更新會引發索引視力的更新。
???????????? 5:索引視圖的創建同時會帶來維護上的開銷。
????????????????? 理由:1:因為索引視圖是物理存在的。
? ? ? ? ? ? ? ? ? ? ? ? ?? 2:要額外的維護索引.
?????????????
???? 實現:SQL:select 字段 from order
??????????? inner join memberView on
????????????? order.cardNo=member.cardNo
??????????????? and member.proxyID=in('a-01',代理號二)
???????????????? and 時間 between '20080101' and '20080131'
?
? ? ?
總結:
兩種解決方案來看,各有所長,一般可以優先考慮使用索引視圖來優化大表關聯。以上是本人對于如何盡量避免發生大表關聯所采取的措施,望大家指教。
?
注:
?? 本文參考:http://www.51cto.com/html/2005/1115/11396.htm
?????
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
