回覆列表
  • 1 # kukkp488

    影響查詢效率的因素    SQLServer處理查詢計劃的過程是這樣的:在做完查詢語句的詞法、語法檢查之後,將語句提交給SQLServer的查詢最佳化器,查詢最佳化器透過檢查索引的存在性、有效性和基於列的統計資料來決定如何處理掃描、檢索和連線,並生成若干執行計劃,然後透過分析執行開銷來評估每個執行計劃,從中選出開銷最小的執行計劃,由預編譯模組對語句進行處理並生成查詢規劃,然後在合適的時間提交給系統處理執行,最後將執行結果返回給使用者。所以,SQLServer中影響查詢效率的因素主要有以下幾種:  1.沒有索引或者沒有用到索引。索引是資料庫中重要的資料結構,使用索引的目的是避免全表掃描,減少磁碟I/O,以加快查詢速度。  2.沒有建立計算列導致查詢不最佳化。  3.查詢出的資料量過大(可以採用多次查詢,其他的方法降低資料量)。  4.返回了不必要的行和列。  5.查詢語句不好,沒有最佳化。其中包括:查詢條件中運算子使用是否得當;查詢條件中的資料型別是否相容;對多個 表查詢時,資料表的次序是否合理;多個選擇條件查詢時,選擇條件的次序是否合理;是否合理安排聯接選擇運算等。SQLServer資料查詢最佳化方法    3.1建立合適的索引  索引是資料庫中重要的資料結構,它的根本目的就是為了提高查詢效率。當根據索引碼的值搜尋資料時,索引提供了對資料的快速訪問。事實上,沒有索引,資料庫也能根據SELECT語句成功地檢索到結果,但隨著表變得越來越大,使用“適當”的索引的效果就越來越明顯。索引的使用要恰到好處,其使用原則有:  (1)對於基本表,不宜建立過多的索引;  (2)對於那些查詢頻度高,實時性要求高的資料一定要建立索引,而對於其他的資料不考慮建立索引;  (3)在經常進行連線,但是沒有指定為外來鍵的列上建立索引;  (4)在頻繁進行排序或分組(即進行groupby或 orderby操作)的列上建立索引;  (5)在條件表示式中經常用到的不同值較多的列上建立檢索,在不同值少的列上不要建立索引。比如在僱員表的“性別”列上只有“男”與“女”兩個不同值,因此就無必要建立索引。如果建立索引不但不會提高查詢效率,反而會嚴重降低更新速度;  (6)如果待排序的列有多個,可以在這些列上建立複合索引。  在SQLServer中,索引按索引表示式包含的列分為單列索引和複合索引。檢查查詢語句的where子句,因為這是最佳化器重要關注的地方。包含在where裡面的每一列都是可能的侯選索引,為能達到最優的效能,例如:對於在where子句中給出了 column1這個列,下面的兩個條件可以提高索引的最佳化查詢效能!第一:在表中的column1列上有一個單索引;第二:在表中有多索引,但是 column1是第一個索引的列。避免定義多索引而column1是第二個或後面的索引,這樣的索引不能最佳化伺服器效能。例如:下面的例子用了pubs資料庫。  SELECTau_id,au_lname,au_fname  FROMauthorsWHEREau_lname=’White’  按下面幾個列上建立的索引將會是對最佳化器有用的索引  au_lname  au_lname,au_fname  而在下面幾個列上建立的索引將不會對最佳化器起到好的作用  au_address  au_fname,au_lname  在SQLServer中,索引按儲存結構分為聚簇索引和非聚簇索引。聚簇索引是按照定義資料列值的順序在物理上對記錄排序,在一個表上只能有一個聚簇索引,聚簇索引查詢速度較快,但缺點是對錶進行修改操作時速度較慢,因為為了保證表中記錄的物理順序與索引的順序一致,必須將記錄插入到資料頁的相應位置,從而資料頁中的資料必須重排。在下面的幾個情況下,可以考慮用聚簇索引:(1)某列包括的不同值的個數是有限的(但是不是極少的)。如顧客表的州名列有50個左右的不同州名的縮寫值,可以使用聚簇索引。  (2)對返回一定範圍內值的列可以使用聚簇索引,如用between,>,>=,   Select*fromsaleswhereord_datebetween’5/1/93’and’6/1/93’  (3)對查詢時返回大量結果的列可以使用聚簇索引。  SELECT*FROMphonebookWHERElast_name=’Smith’  當有大量的行正在被插入表中時,要避免在本表一個自然增長(例如,identity列)的列上建立聚簇索引。如果你建立了聚簇的索引,那麼insert的效能就會大大降低。因為每一個插入的行必須到表的最後,表的最後一個數據頁。  非聚簇索引指定表中的邏輯順序,一個表上可以建立多達249個非聚簇索引,它查詢的速度比不建立索引快,但比聚簇索引慢,插入資料比聚簇索引快,因為紀錄直接被追加到資料末尾。可以在以下情況下考慮使用非聚簇索引。(1)在有很多不同值的列上可以考慮使用非聚簇索引,如employee表中的emp_id列可以建立非聚簇索引。(2)查詢結果集返回的是少量或單行的結果集。例如  select*fromemployeewhereemp_id=’pcm9809f’  (3)查詢語句中orderby子句的列上可以考慮使用非聚簇索引。     3.2常用的計算欄位(如總計、最大值等)可以考慮儲存到資料庫實體中。  例如倉庫管理系統中有材料入庫表,其欄位為:材料編號、材料名稱、型號,單價,數量…,而金額是使用者經常需要在查詢和報表中用到的,在表的記錄量很大時,有必要把金額作為一個獨立的欄位加入到表中。這裡可以採用觸發器以在客戶端保持資料的一致性。     3.3用where子句來限制必須處理的行數。  在執行一個查詢時,用一個where子句來限制必須處理的行數,除非完全需要,否則應該避免在一個表中無限制地讀並處理所有的行。例如:  |||   select qty from sales where stor_id=’7131’是很有效的,比無限制的查詢selectqtyfromsales有效,避免給客戶的最後資料選擇返回大量的結果集。當然也可以用TOP限制返回結果集的行數。     3.4儘量使用數字型欄位。  一部分開發人員和資料庫管理人員喜歡把包含數值資訊的欄位設計為字元型,這會降低查詢和連線的效能,並會增加儲存開銷。這是因為引擎在處理查詢和連接回逐個比較字串中每一個字元,而對於數字型而言只需要比較一次就夠了。     3.5查詢語句的最佳化。  對於一條複雜的查詢語句來說,對相同查詢條件的實現一般總可以有多種不同的表達方法,而不同的表達會使資料庫的響應速度大相徑庭。據統計,約有80%以上的效能問題是由於使用了不恰當的查詢語句造成的,因此SQL語句的質量對整個系統效率有重大關係。下面介紹查詢語句最佳化方面的一些技巧:(1)避免使用不相容的資料型別。例如float和int、char和varchar、 binary和varbinary是不相容的。資料型別的不相容可能使最佳化器無法執行一些本來可以進行的最佳化操作。例如:   SELECTnameFROMemployeeWHEREsalary>60000  在這條語句中,如salary欄位是money型的,則最佳化器很難對其進行最佳化,因為60000是個整型數。這條語句可以改為:  SELECTnameFROMemployeeWHEREsalary>$60000  (2)儘量避免在Where條件裡使用非聚合表示式,因為非聚合表示式很難利用到索引,通常SQLServer不得不進行大規模的掃描。像!=或<>、 ISNULL或ISNOTNULL、IN,NOTIN等這樣的運算子構成的表示式都是非聚合表示式。非聚合表示式會導致查詢效率大大降低。例如:   SELECTidFROMemployeeWHEREid!="B%"  最佳化器將無法透過索引來確定將要命中的行數,因此需要搜尋該表的所有行。   (3)儘量避免在WHERE子句中對欄位進行函式或表示式操作,這將導致引擎放棄使用索引而進行全表掃描。如:  SELECT*FROMemployeeWHEREsalary/2=100應改為: SELECT*FROMemployeeWHEREsalary=100*2   SELECT*FROMemployeeWHERESUBSTRING(emp_id,1,3)=’PCM’應改為:SELECT*FROMemployeeWHEREemp_idLIKE‘5378%’   SELECTmember_number,first_name,last_nameFROMmembers   WHEREDATEDIFF(yy,datofbirth,GETDATE())>21應改為:SELECT member_number,first_name,last_name FROM members WHERE dateofbirth  即:任何對列的操作都將導致表掃描,它包括資料庫函式、計算表示式等等,查詢時要儘可能將操作移至等號右邊。(4)避免使用LEFTJOIN   SQL的一個有價值的常用功能是LEFTJOIN。它可以用於檢索第一個表中的所有行、第二個表中所有匹配的行、以及第二個表中與第一個表中不匹配的所有行。例如,如果希望返回每個客戶及其定單,使用LEFTJOIN則可以顯示有定單和沒有定單的客戶。LEFTJOIN消耗的資源非常之多,因為它們包含與 NULL(不存在)資料匹配的資料。因此在構造查詢語句時儘量避免使用LEFTJOIN。(5)儘量避免在索引過的字元資料中,使用非打頭字母搜尋。這也使得引擎無法利用索引。  見如下例子:  SELECT*FROMmembersWHEREfirst_nameLIKE‘%MA%’   SELECT*FROMmembersWHERESUBSTING(first_name,3,1)=’MA’   SELECT*FROMmembersWHEREfirst_nameLIKE‘MA%’  即使NAME欄位建有索引,前兩個查詢依然無法利用索引完成加快操作,引擎不得不對全表所有資料逐條操作來完成任務。而第三個查詢能夠使用索引來加快操作。(6)避免相關子查詢  一個列的標籤同時在主查詢和 WHERE子句中的查詢中出現,那麼很可能當主查詢中的列值改變之後,子查詢必須重新查詢一次。查詢巢狀層次越多,效率越低,因此應當儘量避免子查詢。可 以採用子查詢“展平”技術,將子查詢轉變為連線,半連線或反連線,從而達到最佳化查詢的目的。例如查詢找出有工資超過10000的職工所在的部門名稱。   SELECT部門名FROM部門WHERE部門號IN  (SELECT部門號FROM職工WHERE工資>10000)  此查詢將掃描部門表的 每一行查詢所有滿足子查詢條件的職工記錄。可以將部門表作為連線的內表,在這種情況下,查詢作為通常的連線來執行,首先對職工表進行唯一的部門號篩選,以 消除冗餘的部門號,轉化後的語句為:  SELECTB.部門名FROM(SELECTDISTINCT部門號FROM職工WHERE工 資>10000,部門DWHEREB.部門號=D.部門號  對於SQL語句的最佳化方法還有很多,在這裡就不一一例舉了。

  • 2 # 使用者4163059234182

    在安裝有SQLServer資料庫的計算機上,我們在使用資料庫的過程中,有時候會在任務管理器裡發現sqlservr.exe這個程序的記憶體和CPU佔用率較高。

    5

    個人建議設定本機記憶體的一半或稍微高一點,如機器記憶體為2G,那麼我們這裡填寫1000。需要注意的是記憶體設定調小以後,在資料庫執行較複雜SQL語句的時候,可能會比較慢,出現這種情況,我們再適當上調最大記憶體配置大小。

  • 中秋節和大豐收的關聯?
  • 泥鰍的身體發紅是怎麼回事?應該怎麼辦?