在SQLServer處理中的一些問題及解決方法

bq_wang發表於2010-07-19

一、DBLINK效能問題
select * from dbsource.dbname.dbo.table where guid in (
select guid from tablechangelog
where tablename='table ' and id<110000)
這個執行居然要40秒以上。
後來分析了一下
1、table和tablechangelog是在不同的伺服器上
2、在tablechangelog有230萬記錄,ID是聚集索引
     在table上guid是主鍵,大概有30萬條記錄
解決步驟
首先執行select guid from tablechangelog where tablename='table ' and id<110000,發現時間忽略不計
再次還原到同一臺伺服器上測試執行,發現只要1秒
select * from table where guid in (
select guid from tablechangelog
where tablename='table ' and id<110000)
也就是說該SQL語句效能瓶頸在於網路,而不是SQL本身。
既然問題在於網路,那應該可以透過減少資料網路傳遞來解決部分
登陸到目標伺服器上執行
select * from table where guid in (
select guid from dbdest.dbname.dbo. tablechangelog
where tablename='table ' and id<110000)
發現只需要1~3秒即可
本來想GUID應該是造成該SQL執行的最大問題,沒想到居然是網路問題
既然最佳化已到達效果,就暫且不用去管GUID了

後話:
對於sqlserver的執行計劃以及I/O、CPU之類的指標看起來實在費勁,與其研究這些,不如靠實證來解決,呵呵

問題二
關於GUID和遞增性ID帶來的問題
出於唯一性和系統維護的要求,在各個表中都存在以下兩個欄位GUID和ID,ID一般為聚集索引+主鍵
[GUID] [varchar] (38) COLLATE Chinese_PRC_CI_AS NOT NULL CONSTRAINT [DF_GUID] DEFAULT ('{' + convert(char(36),newid()) + '}'),
ID  [int] IDENTITY (1, 1) NOT NULL ,

出於系統維護的要求,一般都會這樣查詢
select * from tableA where guid not in (select guid) from tableB)
但是GUID是不做唯一索引的,且即使加了唯一索引,考慮到GUID是無序且過於分散的,如果有幾千上萬的guid的話,仍是不會走索引的


關於ID,ID一般是遞增的,是不要進行維護即可從資料庫中獲得的,同時由ado直接返回給前端程式,以便定位和顯示、
INSERT INTO jobs (job_desc,min_lvl,max_lvl)
VALUES ('Accountant',12,125)
SELECT @@IDENTITY AS 'Identity'

但是再由sqlserver2000升級到sqlserver2008後,發現返回的@@identtiy明顯是錯誤的
後來查了一下SQLServer2000聯機幫助
在一條 INSERT、SELECT INTO 或大容量複製語句完成後,@@IDENTITY 中包含此語句產生的最後的標識值。若此語句沒有影響任何有標識列的表,則 @@IDENTITY 返回 NULL。若插入了多個行,則會產生多個標識值,@@IDENTITY 返回最後產生的標識值。如果此語句激發一個或多個執行產生標識值的插入操作的觸發器,則語句執行後立即呼叫 @@IDENTITY 將返回由觸發器產生的最後的標識值。若 INSERT 或 SELECT INTO 語句失敗或大容量複製失敗,或事務被回滾,則 @@IDENTITY 值不會還原為以前的設定。
發現透過
SELECT IDENT_CURRENT('tablename')能夠返回正確的遞增值
但是否能獲取這個值,不得而知

從sqlserver2005以後系統提供了NEWSEQUENTIALID (),這個新的guid
Creates a GUID that is greater than any GUID previously generated by this function on a specified computer since Windows was started. After restarting Windows, the GUID can start again from a lower range, but is still globally unique. When a GUID column is used as a row identifier, using NEWSEQUENTIALID can be faster than using the NEWID function. This is because the NEWID function causes random activity and uses fewer cached data pages. Using NEWSEQUENTIALID also helps to completely fill the data and index pages.
這個guid是由作業系統產生的,但是每個guid都會比前一個guid要大,這即解決了唯一性問題,又解決了排序問題
目前開發人員正準備按這個思路進行修改

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/6517/viewspace-668415/,如需轉載,請註明出處,否則將追究法律責任。

相關文章