程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> 其他數據庫知識 >> MSSQL >> SQL Server中的SQL語句優化與效力成績

SQL Server中的SQL語句優化與效力成績

編輯:MSSQL

SQL Server中的SQL語句優化與效力成績。本站提示廣大學習愛好者:(SQL Server中的SQL語句優化與效力成績)文章只能為提供參考,不一定能成為您想要的結果。以下是SQL Server中的SQL語句優化與效力成績正文


許多人不曉得SQL語句在SQL SERVER中是若何履行的,他們擔憂本身所寫的SQL語句會被SQL SERVER誤會。好比:

select * from table1 where name='zhangsan' and tID > 10000

和履行:

select * from table1 where tID > 10000 and name='zhangsan'

一些人不曉得以上兩條語句的履行效力能否一樣,由於假如簡略的從語句前後上看,這兩個語句切實其實是紛歧樣,假如tID是一個聚合索引,那末後一句僅僅從表的10000條今後的記載中查找就好了;而前一句則要先從全表中查找看有幾個name='zhangsan'的,爾後再依據限制前提前提tID>10000來提出查詢成果。
  現實上,如許的擔憂是不用要的。SQL SERVER中有一個“查詢剖析優化器”,它可以盤算出where子句中的搜刮前提並肯定哪一個索引能減少表掃描的搜刮空間,也就是說,它能完成主動優化。
  固然查詢優化器可以依據where子句主動的停止查詢優化,但年夜家依然有需要懂得一下“查詢優化器”的任務道理,如非如許,有時查詢優化器就會不依照您的本意停止疾速查詢。
  在查詢剖析階段,查詢優化器檢查查詢的每一個階段並決議限制須要掃描的數據量能否有效。假如一個階段可以被用作一個掃描參數(SARG),那末就稱之為可優化的,而且可以應用索引疾速取得所需數據。
  SARG的界說:用於限制搜刮的一個操作,由於它平日是指一個特定的婚配,一個值得規模內的婚配或許兩個以上前提的AND銜接。情勢以下:

列名 操作符 <常數 或 變量>

<常數 或 變量> 操作符列名列名可以湧現在操作符的一邊,而常數或變量湧現在操作符的另外一邊。如:

Name='張三'

價錢>5000

5000<價錢

Name='張三' and 價錢>5000  

假如一個表達式不克不及知足SARG的情勢,那它就沒法限制搜刮的規模了,也就是SQL SERVER必需對每行都斷定它能否知足WHERE子句中的一切前提。所以一個索引關於不知足SARG情勢的表達式來講是無用的。

引見完SARG後,我們來總結一下應用SARG和在理論中碰到的和某些材料上結論分歧的經歷:

1、Like語句能否屬於SARG取決於所應用的通配符的類型

--如:
name like '張%' --,這就屬於SARG

--而:
name like '%張' --,就不屬於SARG。

緣由是通配符%在字符串的守舊使得索引沒法應用。

2、or 會惹起全表掃描
  Name='張三' and 價錢>5000 符號SARG,而:Name='張三' or 價錢>5000 則不相符SARG。應用or會惹起全表掃描。

3、非操作符、函數惹起的不知足SARG情勢的語句
  不知足SARG情勢的語句最典范的情形就是包含非操作符的語句,如:NOT、!=、<>、!<、!>、NOT EXISTS、NOT IN、NOT LIKE等,別的還有函數。上面就是幾個不知足SARG情勢的例子:

ABS(價錢)<5000

Name like '%三'

--有些表達式,如:

WHERE 價錢*2>5000

--SQL SERVER也會以為是SARG,SQL SERVER會將此式轉化為:
WHERE 價錢>2500/2

但我們不推舉如許應用,由於有時SQL SERVER不克不及包管這類轉化與原始表達式是完整等價的。

4、IN 的感化相當與OR

語句:

Select * from table1 where tid in (2,3)

--和

Select * from table1 where tid=2 or tid=3

是一樣的,都邑惹起全表掃描,假如tid上有索引,其索引也會掉效。

5、盡可能罕用NOT

6、exists 和 in 的履行效力是一樣的
  許多材料上都顯示說,exists要比in的履行效力要高,同時應盡量的用not exists來取代not in。但現實上,我實驗了一下,發明兩者不管是後面帶不帶not,兩者之間的履行效力都是一樣的。由於觸及子查詢,我們實驗此次用SQL SERVER自帶的pubs數據庫。運轉前我們可以把SQL SERVER的statistics I/O狀況翻開:

(1)
select title,price from titles where title_id in (select title_id from sales where qty>30)

該句的履行成果為:

表 'sales'。掃描計數 18,邏輯讀 56 次,物理讀 0 次,預讀 0 次。
表 'titles'。掃描計數 1,邏輯讀 2 次,物理讀 0 次,預讀 0 次。

(2)
select title,price from titles
  where exists (select * from sales
  where sales.title_id=titles.title_id and qty>30)

第二句的履行成果為:

表 'sales'。掃描計數 18,邏輯讀 56 次,物理讀 0 次,預讀 0 次。
表 'titles'。掃描計數 1,邏輯讀 2 次,物理讀 0 次,預讀 0 次。

我們從此可以看到用exists和用in的履行效力是一樣的。

7、用函數charindex()和後面加通配符%的LIKE履行效力一樣
  後面,我們談到,假如在LIKE後面加上通配符%,那末將會惹起全表掃描,所以其履行效力是低下的。但有的材料引見說,用函數charindex()來取代LIKE速度會有年夜的晉升,經我實驗,發明這類解釋也是毛病的:

select gid,title,fariqi,reader from tgongwen
   where charindex('刑偵支隊',reader)>0 and fariqi>'2004-5-5'

用時:7秒,別的:掃描計數 4,邏輯讀 7155 次,物理讀 0 次,預讀 0 次。

select gid,title,fariqi,reader from tgongwen
   where reader like '%' + '刑偵支隊' + '%' and fariqi>'2004-5-5'

用時:7秒,別的:掃描計數 4,邏輯讀 7155 次,物理讀 0 次,預讀 0 次。

8、union其實不相對比or的履行效力高
  我們後面曾經談到了在where子句中應用or會惹起全表掃描,普通的,我所見過的材料都是推舉這裡用union來取代or。現實證實,這類說法關於年夜部門都是實用的。

select gid,fariqi,neibuyonghu,reader,title from Tgongwen
   where fariqi='2004-9-16' or gid>9990000

用時:68秒。掃描計數 1,邏輯讀 404008 次,物理讀 283 次,預讀 392163 次。

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16'
union
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid>9990000

用時:9秒。掃描計數 8,邏輯讀 67489 次,物理讀 216 次,預讀 7499 次。

看來,用union在平日情形下比用or的效力要高的多。

但經由實驗,筆者發明假如or雙方的查詢列是一樣的話,那末用union則反倒和用or的履行速度差許多,固然這裡union掃描的是索引,而or掃描的是全表。

select gid,fariqi,neibuyonghu,reader,title from Tgongwen
   where fariqi='2004-9-16' or fariqi='2004-2-5'

用時:6423毫秒。掃描計數 2,邏輯讀 14726 次,物理讀 1 次,預讀 7176 次。

select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-9-16'
union
select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi='2004-2-5'

用時:11640毫秒。掃描計數 8,邏輯讀 14806 次,物理讀 108 次,預讀 1144 次。

9、字段提取要依照“需若干、提若干”的准繩,防止“select *”

  我們來做一個實驗:

select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc
用時:4673毫秒
select top 10000 gid,fariqi,title from tgongwen order by gid desc
用時:1376毫秒
select top 10000 gid,fariqi from tgongwen order by gid desc
用時:80毫秒

由此看來,我們每少提取一個字段,數據的提取速度就會有響應的晉升。晉升的速度還要看您捨棄的字段的年夜小來斷定。

10、count(*)不比count(字段)慢
  某些材料上說:用*會統計一切列,明顯要比一個世界的列名效力低。這類說法實際上是沒有依據的。我們來看:

select count(*) from Tgongwen
用時:1500毫秒

select count(gid) from Tgongwen
用時:1483毫秒

select count(fariqi) from Tgongwen
用時:3140毫秒

select count(title) from Tgongwen
用時:52050毫秒

從以上可以看出,假如用count(*)和用count(主鍵)的速度是相當的,而count(*)卻比其他任何除主鍵之外的字段匯總速度要快,並且字段越長,匯總的速度就越慢。我想,假如用count(*), SQL SERVER能夠會主動查找最小字段來匯總的。固然,假如您直接寫count(主鍵)將會來的更直接些。

11、order by按集合索引列排序效力最高
  我們來看:(gid是主鍵,fariqi是聚合索引列):

select top 10000 gid,fariqi,reader,title from tgongwen

用時:196 毫秒。 掃描計數 1,邏輯讀 289 次,物理讀 1 次,預讀 1527 次。

select top 10000 gid,fariqi,reader,title from tgongwen order by gid asc

用時:4720毫秒。 掃描計數 1,邏輯讀 41956 次,物理讀 0 次,預讀 1287 次。

select top 10000 gid,fariqi,reader,title from tgongwen order by gid desc
用時:4736毫秒。 掃描計數 1,邏輯讀 55350 次,物理讀 10 次,預讀 775 次。

select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi asc
用時:173毫秒。 掃描計數 1,邏輯讀 290 次,物理讀 0 次,預讀 0 次。

select top 10000 gid,fariqi,reader,title from tgongwen order by fariqi desc
用時:156毫秒。 掃描計數 1,邏輯讀 289 次,物理讀 0 次,預讀 0 次。

從以上我們可以看出,不排序的速度和邏輯讀次數都是和“order by 集合索引列” 的速度是相當的,但這些都比“order by 非集合索引列”的查詢速度是快很多的。
  同時,依照某個字段停止排序的時刻,不管是正序照樣倒序,速度是根本相當的。

12、高效的TOP
  現實上,在查詢和提取超年夜容量的數據集時,影響數據庫呼應時光的最年夜身分不是數據查找,而是物理的I/0操作。如:

select top 10 * from (
select top 10000 gid,fariqi,title from tgongwen
where neibuyonghu='辦公室'
order by gid desc) as a
order by gid asc

這條語句,從實際上講,整條語句的履行時光應當比子句的履行時光長,但現實相反。由於,子句履行後前往的是10000筆記錄,而整條語句僅前往10條語句,所以影響數據庫呼應時光最年夜的身分是物理I/O操作。而限制物理I/O操作此處的最有用辦法之一就是應用TOP症結詞了。TOP症結詞是SQL SERVER中經由體系優化過的一個用來提取前幾條或前幾個百分比數據的詞。經筆者在理論中的運用,發明TOP確切很好用,效力也很高。但這個詞在別的一個年夜型數據庫ORACLE中卻沒有,這不克不及說不是一個遺憾,固然在ORACLE中可以用其他辦法(如:rownumber)來處理。在今後的關於“完成萬萬級數據的分頁顯示存儲進程”的評論辯論中,我們就將用到TOP這個症結詞。

到此為止,我們下面評論辯論了若何完成從年夜容量的數據庫中疾速地查詢出您所須要的數據辦法。固然,我們引見的這些辦法都是“軟”辦法,在理論中,我們還要斟酌各類“硬”身分,如:收集機能、辦事器的機能、操作體系的機能,乃至網卡、交流機等。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved