K3数据库优化方案
K/3 系統性能優化解決方案?作者:詩歡
--重建索引速度較慢,請在系統空閑時間進行
DBCC DBREINDEX(t_icitem)
DBCC DBREINDEX(t_item)
DBCC DBREINDEX(t_itemclass)
DBCC DBREINDEX(t_itemright)
DBCC DBREINDEX(t_user)
DBCC DBREINDEX(t_group)
go
if not exists(select 1 from sysindexes where name='ix_group_fgroupid')
create index ix_group_fgroupid on t_group(fgroupid)
go
if not exists(select 1 from sysindexes where name='ix_itemright_ftypeid')
create index ix_itemright_ftypeid on t_itemright(ftypeid)
go
1 SQL Server調整
當用戶使用K3系統一段時間以后,發現系統的響應時間越來越長。這種情形往往是由于賬套數據庫缺乏維護引起的。缺乏維護的數據庫會存在過多地碎片、過期的統計、隱含著可能的錯誤查詢結果的數據庫的邏輯和物理的不一致性,這些都會直接影響系統的性能。這里介紹解決上述賬套數據庫性能問題常用的方法。
1.1 使用DBCC語句發現和解決上述問題。
DBCC:?數據庫一致性檢查器。
打開SQL?查詢分析器?,執行如下語句。
?
u?DBCC SHOWCONTIG?顯示指定表的數據和索引的有關數據碎片的信息DBCC SHOWCONTIG(表名[,索引名])
在有大的改動的表,引入數據的表,或者引起低效查詢的表上使用該語句。
例:DBCC SHOWCONTIG(’T_ITEM’)
u?DBCC DBREINDEX?重建指定數據庫中表的一個或多個索引。
例1:重建某個索引
???????????????????????????????DBCC?DBREINDEX?('T_ITEM',?uk_item2,?80)例2:重建所有索引
DBCC DBREINDEX ('T_ITEM',’’,80)
?
u?DBCC SHOW_STATISTICS?顯示指定表上的指定目標(例如一個索引名稱))的當前分布統計信息。這些統計信息是被SQL Server查詢優化器使用的DBCC SHOW_STATISTICS(表名,目標)
例:DBCC SHOW_STATISTICs('t_item','pk_item')
u?sp_updatestats & UPDATE STATISTICS?更新統計信息;?sp_updatestats?對當前數據庫中所有?用戶定義的表運行 UPDATE STATISTICS.
使用UPDATE STATISTICS?語句的時機:在一個空表上創建一個索引,然后在以后應用它。執行TRUNCATE TABLE語句,然后在以后重新應用該表。通過使用FULLSCAN或SAMPLE選項請求明細的索引統計信息。
例1. UPDATE STATISTICS T_ITEM
例2. UPDATE STATISTICS T_ITEM(PK_ITEM)
例?3.?USE?AIS20011203150410
EXEC sp_updatestats
?
u?DBCC CHECKTABLE?檢查指定表或索引視圖的數據、索引及?text?、ntext?和?p_w_picpath?頁的完整性。如果你相信一個指定的表可能被破壞了,這條命令非常有用。
u?DBCC CHECKDB?檢查指定數據庫中的所有對象的分配和結構完整性。這條命令發現并修復數據庫地址分配和表內部的全部錯誤。實際上,CHECKDB驗證數據庫內部一切事物的完整性,但是,DBCC CHECKDB是一個耗費CPU和磁盤資源的操作,每個需要檢查的數據都必須首先從磁盤中讀出到內存中。而且,DBCC CHECKDB 使用tempdb進行排序 。要獲得較高的DBCC性能,推薦在下面的情況下運行DBCC:
?
l 在系統使用率較低的情況下運行CHECKDB;
l 確信當前沒有執行其他磁盤I/O操作,如磁盤備份操作;
l 將tempdb放在另一個磁盤系統上,或者放在一個快速磁盤子系統上;
l 為tempdb提供足夠的空間,運行DBCC帶上參數ESTIMATE ONLY(顯示執行?DBCC CHECKDB?操作所需tempdb?空間的數量?),估計tempdb需要多少磁盤空間;
l 避免運行消耗大量CPU時間的查詢和批處理;
l 在DBCC命令運行時,減少事物活動;
l 使用NO_INFOMSGS選項(壓縮使用空間使用的信息和報告?)減少處理和tempdb使用率。
例:DBCC CHECKDB ('AIS20011203150410') WITH NO_INFOMSGS,ESTIMATEONLY
u?DBCC SQLPERF?提供有關所有數據庫中的事務日志空間使用情況的統計信息。日志文件的閑余空間的減少,會降低系統的性能。系統會在備份時日志截斷日志文件,所以要求用戶要制定一份良好的備份方案。
例:DBCC SQLPERF ( LOGSPACE )
1.2 使用數據庫維護計劃
使用數據庫維護計劃器是一種標準且方便的可對多個賬套數據庫同時設置維護任務維護模式。下面介紹其建立方法:
本方案所介紹的數據庫維護計劃側重于數據庫的優化,即性能的提高。
1) 打開Enterprise Manager,展開服務器,展開管理,然后單擊數據庫維護計劃。從操作(Action)中選擇新建維護計劃?,可以看到圖4.1所示的歡迎屏幕,單擊下一步按鈕。
2) 選擇數據庫,選擇K3賬套所在的數據庫(可選一個或多個)。單擊下一步按鈕。
圖2 選擇數據庫
3) 更新數據庫優化信息。選擇重新組織數據和索引頁,選擇使用原有可用空間重新組織頁面。選擇當增長超過50MB時,從數據庫文件中刪除未使用空間,收縮后保留的可用空間為10%的數據空間。單擊下一步按鈕。
圖3更新數據庫優化信息
4) 檢查數據庫完整性。選擇檢查數據庫完整性,包含索引以及嘗試修復所有小問題。單擊下一步。
圖4 檢查數據庫完整性
5) 指定數據庫備份計劃,備份在優化方案中暫不考慮,跳過,單擊下一步。
圖5數據庫備份計劃
6) 指定事務日志備份計劃在優化方案中暫不考慮,跳過,單擊下一步。
圖6指定事物備份計劃
7) 生成報表。選擇將報表寫入目錄中的文本文件,選擇刪除早于4周的報表文件?;蛘哌x擇將電子郵件報表發送到操作員,然后花時間閱讀這個報表,看看數據庫中是否有任何需要注意的問題。單擊下一步。
圖7生成報表
8) 維護計劃歷史記錄。
SQL Server每次運行時保持維護計劃的歷史??梢詾g覽這個歷史,看看操作中何時遇到故障,然后確定故障原因。如果只有單臺機器,則要在本地服務器存放歷史紀錄,但如果網絡中又多臺機器,則要將歷史紀錄存放在中央服務器中,以便從各臺機器上方便的訪問。下面選擇缺省在本地存放1000行歷史紀錄。單擊下一步。
圖 8 維護歷史紀錄
9) 完成數據庫維護計劃向導。用于命名和檢查具體工作,在計劃名中輸入:K3賬套數據庫維護計劃。單擊完成按鈕生成計劃。
圖9 完成數據庫維護計劃向導
1.3 發現死鎖和消除死鎖
死鎖形成的原因是不同的,有的死鎖系統可以自動地偵測和消除而另外一些則需要管理員調整請求
死鎖發生在兩個或多個進程同時等待被其中一個進程保留著的鎖。該進程將不會釋放它保留的鎖直到它獲得被其它進程保留的資源,反過來也一樣。當一個死鎖被被確認以后,SQL Server通過自動選擇可以立即打斷死鎖的線程來結束死鎖。
許多阻塞的問題發生在由于一個進程保留鎖過長時間,引起一系列被阻塞的進程等待其它進程釋放鎖。SQL Server不能識別阻塞鎖并自動地解決它們,所以必須監控阻塞鎖的存在并手工消除它。
在一個應用中建立一個鎖的超時設置是一個防止阻塞鎖的方法。這允許應用監控阻塞鎖并回滾進程而不是不確定地等待或阻塞語句的重提交。
下面,介紹手工消除死鎖的方法:
1) 系統長時間沒有響應,可以在SQL查詢分析器中執行系統存儲過程sp_lock?和sp_who?,?如圖所示,spid 57正在等待資源。
Spid?:系統進程?ID
執行命令:sp_who 57?可以得到關聯該進程和鎖的用戶的登錄名稱,主機名稱和狀態等信息。
圖1. 運行sp_lock顯示的鎖信息
2) 轉到SQL Server Enterprise Manager,展開管理?,展開當前活動,?展開鎖?/?進ID?,如圖所示,spid57被spid56阻塞。
圖2. 顯示鎖的阻塞情況
3) 雙擊spid56,然后單擊取消進程?(Kill Process)。
4) spid57阻塞解除。
2 硬件調整
硬件調整,是為K3系統的正常運行要求的工作量提供足夠的硬件資源的行動。要調整系統的硬件,就要決定可以為K3系統分配那些資源以改進其性能,這些資源包括附加的內存、CPU、I/O資源或所有這些資源的組合。調整系統性能的工作主要涉及決定應該增加哪種資源,以及增加多少資源。
硬件調整是非常重要的,因為許多典型的性能問題是由不充足的或配置失當的硬件組件導致的。I/O子系統是一個數據庫調整的關鍵性部分。通過提供足夠的CPU、內存與I/O資源。可以避免許多性能問題。
通過監控相關的計數器,可以及時發現和解決引起系統性能降低的硬件問題。
2.1 控制內存的使用
SQL Server 要求內存是基于靜態內存的需要:一是它自己的程序代碼和內部數據結構,例如內核的工作負載,打開對象,鎖。二是數據高速緩存。
基于有效的系統資源和這些資源的競爭需要, SQL Server動態地獲得和釋放數據高速緩存。如果SQL Server的數據高速緩存需要更多的內存,它查詢操作系統檢查是否有物理內存可以利用。如果有,SQL Server在數據高速
存中使用它并且在內存中保留先前讀到的數據。
為阻止Windows 2000頁面調度,SQL Server依賴Server activity增減數據高速緩存以保留4MB~10MB剩余物理內存。對SQL Server不足的內存分配或使用會引起數據連續地從硬盤上而不是高速緩存上讀取,這將降低系統的性能。
請觀察以下與內存有關的計數器,以便及時發現和解決內存上的問題。
使用工具:性能監視器
監控內存和分頁的使用
對象:?計數器
描述
指導
Memory: Available Bytes
監控被進程執行使用的有效字節數。
(可用物理內存量)
這個計數器應該總是大于5000KB;低值顯示物理內存整體的缺乏和需要提高。
推薦值:大于4MB
Memory: Page/sec
為了訪問不在內存中的頁而讀取或寫入磁盤的總頁數。
該計數器應該從不持續大于零.如果值持續大于零,Windows 2000操作系統正在使用頁面調度來填充內存.
推薦值:小于5
Process: Page Faults/sec/SQL Server Instance
缺頁/秒
處理器中的Page Faults的計數值。當進程所引用的虛擬內存頁不在其主內存的工作集中時,將發生頁錯誤。如果某一頁已在主內存中(位與備用列表內),或者它正被共享此頁的其他進程使用,Page Fault 將不會導致系統從磁盤調入該頁。
這個計數器的高值表明過多的頁面調度和磁盤壓力,檢查是否是SQL Server 或其他的進程引起過多的頁面調度。
隔離SQL Server 使用的內存
Process: Working Set/SQL Server Instance
監控用于SQL Server的一個實例的SQL Server進程的內存的
數量。
這個計數器應該大于5000KB。當這個計數器低于5000KB,沒有更多的內存可供SQL Server 使用。
SQL Server: Buffer Manager: Buffer Cache Hit Ratio
高速緩存命中率
監控高速緩存中不需從硬盤中讀取的頁的百分率,。不用區分用于高速緩存的是物理內存還是頁面調度內存。
這個計數器應該大于90%,因為它顯示的是發現在內存中的頁的數量。
SQL Server: Buffer Manger: Total Pages
監控高速緩存中頁的總數量,包括數據庫,free和來自其他進程的stolen頁。
低值顯示連續的磁盤輸入輸出或壓力.考慮增加更多的內存.
SQL Server: Memory Manager Total Server Memory
監控服務器正在使用的動態內存的總的數量。
如果該計數器與可用的物理內存比較持續高,則需加更多的內存。
2.2 監控線程和處理器的使用
優化處理器性能是輸出量和響應時間之間的一種平衡。
處理器的性能
當你檢查處理器的使用,考慮SQL Server實例正在做的工作的類型。如果SQL Server正在做大量的計算,例如包含集合的查詢或綁定內存這種不需要磁盤輸入輸出的查詢,100%的處理器時間可能被使用。
對于多處理器的系統,你需要監控每個處理器的這個計數器的分離的實例。確定所有處理器的平均值,可使
計數器:System:% Total Processor Time?。
線程
每個SQL Server的實例都是一個獨立的操作系統進程,SQL Server2000的實例使用Windows線程,有時是纖程
去有效的管理并發的任務。
1) 一個進程是一個應用的實例,例如SQL Server并且能有一個或多個任務。
2) 一個線程是進程任務的一種機制,并且被用來計劃處理器的時間。
當一個線程處于等待一個操作(例如讀寫磁盤)完成的空閑期時,Windows 2000操作系統通過轉換線程來最大化處理器的使用。線程間的轉換叫做context switching.?每個SQL Server的實例用戶連接的一個線程池,池中的線程被叫做工作線程。
當Processor: %Processor Time?持續接近100%并且System: Processor Queue Length?顯示更多的應用的進程正在等待處理器,或者當System: Context Switches/Sec?較高。顯示出現了系統瓶頸。當Processor:% Processor Time?接近100%并且System: Context Switches/Sec?接近8000,考慮更快的處理器,附加的處理器或者轉換到使用纖程。
請觀察以下與內存有關的計數器,以便及時發現和解決處理器上的問題。
使用工具:Windows?性能監視器
對象:?計數器
描述
指導
Processor: %Processor Time
以處理器運行非空閑線程所經歷時間的百分比表示。它被視為用于處理有效工作的時間比。每一個處理器在空閑時將會指定一個空閑線程來消耗未被其他線程使用的處理器時間段。
這個計數器應該低于90%,如果這個計數器較高,應降低工作負荷,提高工作效率或者或加大處理器的能力。
System: Context Switches/sec
監控處理器每秒在線程間轉換的次數。
在一個多處理器的計算機上,如果這個計數器達到8000,并且Processor:% Processor Time計數器超過90%,考慮使用SQL Server fiber scheduling.
System: Processor Queue Length
監控等待進程時間的線程的數目
這個計數器不應該持續大于2。如果這個計數器持續大于2,降低工作負荷,提高工作負荷的效率,或者增加處理器的能力,在多處理器的系統中可以增加處理器。
Processor: % Privileged Time
在“特權模式”下處理器運行非空閑線程所經歷時間的百分比。Windows NT服務層,執行體子程序及Windows NT內核都是在“特權方式”下運行。
如果處理器的大部分時間被用來做系統內核命令,并且物理硬盤的計數器較高,考慮提高硬盤輸入輸出子系統的性能。
Processor: %User Time
在“用戶模式”下處理器運行非空閑線程所經歷時間的百分比。所有應用程序碼及子系統碼都在“用戶模式“下運行。
這個能確定其它進程或應用正在執行或阻止SQL Server操作。
2.3 監控硬盤輸入輸出
SQL Server 使用Windows 2000 I/O calls 執行磁盤的讀寫。SQL Server管理何時和如何執行磁盤讀寫,但依賴Windows執行底層的輸入輸出操作。I/O子系統包括系統總線,磁盤控制卡,磁盤,磁帶驅動器,CD-ROM驅動器和許多其它的I/O設備。磁盤經常是系統的最大的瓶頸。
監控硬盤輸入輸出將幫助你確定讀頁和寫頁是否超出硬盤子系統的能力。一個忙碌的硬盤子系統也可以顯示不足的內存所引起的過多的頁面調度輸入輸出。
下面的表描述了優化對象計數器,你可以用來監控你的硬盤子系統的性能。
使用工具:Windows?性能監視器
對象:計數器
描述
指導
PhysicalDisk: %Disk Time
所選的驅動器忙于處理讀取或寫入請求作服務所花費時間的百分比。
這個計數器應當持續低于90%。
推薦值:小于50%
PhysicalDisk:Avg.Disk Queue Length
指在采樣間隔期內,對所選磁盤的讀寫操作被排入隊列的平均次數。
這個計數器應該不超過中心值的兩倍。
PhysicalDisk:Disk Read/sec
讀取磁盤的速度
這個計數器應該續低于硬盤子系統的能力。
PhysicalDisk: Disk Writes/sec
寫入磁盤的速度
這個計數器應持續低于硬盤子系統的能力。
如果這些硬盤計數器顯示你的硬盤正在超負荷運行,考慮:
1. 通過使用一個更快的硬盤,提高硬盤輸入輸出能力
2. 把一些文件轉移到一個附加硬盤或服務器上
3. 增加一個硬盤陣列
4. 提高硬盤的數量有助于減少硬盤的壓力。
SQL SERVER中一些常見性能問題的總結
1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
2.應盡量避免在 where 子句中對字段進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
select id from t where num=0
3.應盡量避免在 where 子句中使用!=或<>操作符,否則將引擎放棄使用索引而進行全表掃描。
4.應盡量避免在 where 子句中使用 or 來連接條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否則會導致全表掃描,如:
select id from t where num in(1,2,3)
對于連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查詢也將導致全表掃描:
select id from t where name like '%abc%'
若要提高效率,可以考慮全文檢索。
7.如果在 where 子句中使用參數,也會導致全表掃描。因為SQL只有在運行時才會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運
行時;它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將
進行全表掃描:
select id from t where num=@num
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where num=@num
8.應盡量避免在 where 子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改為:
select id from t where num=100*2
9.應盡量避免在where子句中對字段進行函數操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id
select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id
應改為:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
10.不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算,否則系統將可能無法正確使用索引。
11.在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統使用該索引,否則該索引將不會被使用,并且應盡可能的讓字段順序與索引順序相一致。
12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類代碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
create table #t(...)
13.很多時候用 exists 代替 in 是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)
14.并不是所有索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重復時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那么即使在sex上建了索引也對查詢效率起不了作用。
15.索引并不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。
16.應盡可能的避免更新 clustered 索引數據列,因為 clustered 索引數據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引數據列,那么需要考慮是否應將該索引建為 clustered 索引。
17.盡量使用數字型字段,若只含數值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對于數字型而言只需要比較一次就夠了。
18.盡可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長字段存儲空間小,可以節省存儲空間,其次對于查詢來說,在一個相對較小的字段內搜索效率顯然要高些。
19.任何地方都不要使用 select * from t ,用具體的字段列表代替“*”,不要返回用不到的任何字段。
20.盡量使用表變量來代替臨時表。如果表變量包含大量數據,請注意索引非常有限(只有主鍵索引)。
21.避免頻繁創建和刪除臨時表,以減少系統表資源的消耗。
22.臨時表并不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重復引用大型表或常用表中的某個數據集時。但是,對于一次性事件,最好使用導出表。
23.在新建臨時表時,如果一次性插入數據量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數據量不大,為了緩和系統表的資源,應先create table,然后insert。
24.如果使用到了臨時表,在存儲過程的最后務必將所有的臨時表顯式刪除,先 truncate table ,然后 drop table ,這樣可以避免系統表的較長時間鎖定。
25.盡量避免使用游標,因為游標的效率較差,如果游標操作的數據超過1萬行,那么就應該考慮改寫。
26.使用基于游標的方法或臨時表方法之前,應先尋找基于集的解決方案來解決問題,基于集的方法通常更有效。
27.與臨時表一樣,游標并不是不可使用。對小型數據集使用 FAST_FORWARD 游標通常要優于其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數據時。在結果集中包括“合計”的例程通常要比使用游標執行的速度快。如果開發時間允許,基于游標的方法和基于集的方法都可以嘗試一下,看哪一種方法的效果更好。
28.在所有的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每個語句后向客戶端發送 DONE_IN_PROC 消息。
29.盡量避免大事務操作,提高系統并發能力。
30.盡量避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理。
具體的SQL語句在很多情況下需要結合實際的應用情況來寫,這里不作敘述。
--Windows 2003支持4G內存
[boot loader]
timeout=30
default=multi(0)disk(0)rdisk(0)partition(2)/WINDOWS
[operating systems]
multi(0)disk(0)rdisk(0)partition(2)/WINDOWS="Windows Server 2003, Standard" /fastdetect /3GB
將Boot.ini文件加好參數:
/fastdetect /3GB
對數據庫中一些數據量較大的表(如T_Voucher,T_VoucherEntry,T_Balance,
IcStockBill,IcStockBillEntry等)可以在SQL SERVER中制作一個作業在系統空閑時定時進行重建索引,例如“dbcc dbreindex('icstockbill');dbcc dbreindex('icstockbillEntry')”2個sql進行出入庫單據表的專門索引優化。
轉載于:https://blog.51cto.com/211721/1845479
總結
- 上一篇: Unity 打包发布UWP 超详细
- 下一篇: 替换 Wonderware,云原生时序数