SQL Server中的重要观点
以下為重要觀點:
1、通過把數據庫設置成讀已提交快照,在read committed隔離級別下,讀不會阻塞寫,寫也不會阻塞讀,通過嘗試這個觀點是正確的。
2、當連接1請求了共享鎖,2請求了獨占鎖,3請求了共享鎖,4請求了更新鎖時,這四個請求都會進入鎖的請求隊列中,書上說SQL Server的鎖隊列,基本上是按照先進先出的規則,但是會考慮鎖的兼容性,所以這個時候可能1、3、4這3個請求的鎖是兼容的,所以這3個請求會先處理,這個得嘗試一下
一個優化方面的重要的觀點
網友的提問:
大牛們,加了一個or,為什么執行計劃由哈希匹配變成嵌套循環?http://bbs.csdn.net/topics/390599501
select count(*) from t1 where a1='1' and a2 in(select a2 from t2)
select count(*) from t1 where a1='1' and (a2 in(select a2 from t2) or a2='2')
表t1超過100萬條數據,語句1執行時間為1秒,語句2超過80秒,請問為什么,語句2該怎樣修改?
下面是我的回答:
建議把查詢改寫成關聯的,inner join或者是left join,其實要想明白,為什么加了a2='2'后,執行計劃變化了,這個很難,因為這個是由SQL Server的優化器決定的,我們很難猜測優化器在一堆的判斷當中為什么選了nested loop 而不選hash join。
但如果你寫成inner join或者left join的時候,如果速度不佳,你可以通過添加查詢提示,比如hash:inner hash join
其實本質上就是手動給SQL Server的優化器建議,建議他采用hash join,之所以微軟會提供這種查詢提示,就是已經預料到會有你所遇到的問題,所以才提供了這種可以由你來進行微調的技術。
?
下面是一個關于數據庫設計的觀點
下面是網友的一個問題:http://bbs.csdn.net/topics/390631703?page=1#post-395959332
關于倉儲系統的方案設計,以下為現有倉庫表的設計(部分表):
TAB/裝車單:
字段:(裝車單號,倉庫ID,倉庫編碼,倉庫名稱,...創建人NAME,創建時間,修改人NAME,修改時間...)
TAB/裝車單明細表:
字段:(裝車單號,貨物ID,貨物名稱,...創建人NAME,創建時間,修改人NAME,修改時間...)
TAB/采購單:
字段:(采購單號,...創建人NAME,創建時間,修改人NAME,修改時間...)
TAB/采購單明細表:
字段:(進貨商ID,進貨商NAME,采購部門ID,采購部門NAME,...創建人NAME,創建時間,修改人NAME,修改時間...驗貨人NAME,驗貨時間)
?
首先這個不我設計的,我覺那個人這樣的設計的好處就是為了查詢方便(不用做關聯查詢嵌套查詢什么的就能獲得要的數據),但是一旦部門名稱或者管理員名稱(即便可能不修改 但不是絕對的)等等會影響到所有使用這些數據的表。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
我的解決方案
我看到這個庫時候感覺里面太多太多的表都都是這樣的,舉個最明顯的例子,創建人NAME 好多表都存的是 管理員的NAME 而非ID。
我覺的除了把管理員NAME之類的刪除,都換成外鍵。除此 像裝車單里的倉庫編碼、倉庫名稱、等;裝車明細表里的貨物名稱;采購單明細里的采購部門NAME,進貨商NAME都統統刪除 只保留引用的外鍵ID進行設計
之所以這樣修改是為了解決數據冗余問題,但后期在查詢數據時候會涉及更多的嵌套查詢關聯查詢才能解決。不知道各位老蝦怎么看我這樣的處理方案或者給個更好的意見,多謝
===============================================================================
?
下面是我的回復:
其實,你對于表的修改意見,是有道理的。
因為,關系數據庫系統,在設計時,有所謂3NF,一般都要達到這個第三范式,這樣能夠減少數據的冗余。
而且,實際上不僅能夠減少冗余,而且這樣做的好處是由于是通過外鍵來引用基表的id,修改也方便了,
比如,當你的倉庫名稱變化了,你只需要去修改,這些業務表所引用的,基表里面的倉庫名稱。
而你們公司現在的系統,如果你有10個業務表,都有倉庫名稱這個字段,一旦只要有一個倉庫的名稱變化了,那么你就得通過倉庫編號,來連接基表,然后再update這10個表的倉庫名稱,那是非常麻煩的。
應該說,你們公司現在系統的數據存儲方式是采用了反向規范化,也就是冗余化存儲。
你希望采用規范化,而你們公司原來的系統采用的是范規范化。
規范化的好處上面說了,就是減少數據冗余,修改非常容易。
而反向規范化的好處,就是不用子查詢,或者關聯多的表,查詢的性能會好。
總結:
我覺得到底采用哪種方式,這需要你自己權衡,如果你的系統,很少有更新倉庫名稱,也就是很少更新這些基表數據,那么為了提高查詢的性能,而且也不用每次寫查詢,關聯N多基表,那么就還是采用原來的方式。這種方式,在互聯網的應用中比較多,傳統的業務用的不多。
如果系統中會更新這些倉庫名稱,那么還是建議采用外鍵id的方式,來修改這些表的設計,當然啦,語句可能得寫的比較復雜,因為我原來的公司就是都采用外鍵id的,由于這種外鍵很多,公司設計了一個字典表,
比如:dict_table 里面存放了幾乎所有的外鍵id,所引用的id,那么我們公司有一個store表,里面有一堆的id,上面渠道id,公司id,組織id,經銷商id,層級id,性質id等,于是乎,為了取得這些客戶的渠道、公司、組織、經銷商、層級、性質,就得關聯dict_table 至少6次,也就是
select 字段列表
from store
left join dict_table
left join dict_table
left join dict_table
left join dict_table
left join dict_table
left join dict_table
就是這樣,經常一個查詢,得關聯10-15個表左右,語句寫的非常復雜。
所以,呵呵,最后還是得樓主,按照你們公司的特殊情況,業務特點,來選擇,到底是去除冗余,或者是去除部分冗余。
還有下面的,關于數據庫設計的:
我也試了,如果把數據拆分成列,那么到時候,比如:屬性-值,拆分成2行數據,一行存屬性,一行存列,
這樣看上去倒是好一點,但是在查詢的時候,還是得行轉列,比較麻煩。
其實設計表,就是得考慮:性能,業務,占用存儲,開發速度。
我原來的公司,需要非常快的開發速度,于是,就把不同業務的數據,放到一個表中,通過增加一個func_code字段,來區分是不同功能產生的,然后后面是一堆字段,A業務用xx字段,B業務用yy字段,其他都是空著的,這樣的話,非常方便開發,在理解業務的時候,也很容易,不同業務,用不同的字段。
但是,如果你不懂業務,就會很迷惑,看不懂,怎么一眼看過去,一堆沒用的字段放在那兒,全是null。
也想過拆分,但是這樣也麻煩,就是剛才說的,開發的難度就上去了,而且性能也不會太好,因為你得做動態的行轉列,每個業務用到的字段個數,和字段名稱,都不完全一樣,這可非常的麻煩。
所以,你一開始想的還是對的,這種表的設計,雖然看著,有很多null值,但是開發上就比較容易,性能也不錯。
關于通過游標和循環的方式來處理數據的問題:
其實用循環和游標,之所以對性能有影響,根本的原因在于,處理數據的方式,也就是取出1條數據,然后處理,處理完成后,再取出下一條,
如果你的表有1000w條數據,那么就得循環1000w次,效率肯定是非常低的。
同樣的,如果單純的sql語句,之所以性能相對較好的原因在于,他是以集合為單位來處理數據,也就是批處理,一次能把所有的數據都處理好。
當然,有時候,由于業務邏輯非常復雜,可能需要寫多個語句,每個語句先把中間的結果插入到一個臨時表中,然后最后再對臨時表進行處理,這也是一個變通的辦法,但盡量不要用游標或者是循環來處理數據,因為效率比較低。
?
轉載于:https://www.cnblogs.com/momogua/archive/2012/02/05/8304637.html
總結
以上是生活随笔為你收集整理的SQL Server中的重要观点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: css字体设置奇怪问题
- 下一篇: (转载)不一样的冒泡排序