真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

sqlserver邏輯讀,sql思維

sql注入 安全測試 靠參數(shù)過濾可行嗎

首先:我們要了解SQL收到一個指令后所做的事情:具體細(xì)節(jié)可以查看文章:SqlServer編譯、重編譯與執(zhí)行計劃重用原理在這里,我簡單的表示為:收到指令-編譯SQL生成執(zhí)行計劃-選擇執(zhí)行計劃-執(zhí)行執(zhí)行計劃。具體可能有點(diǎn)不一樣,但大致的步驟如上所示。接著我們來分析為什么拼接SQL字符串會導(dǎo)致SQL注入的風(fēng)險呢?首先創(chuàng)建一張表Users:CREATETABLE[dbo].[Users]([Id][uniqueidentifier]NOTNULL,[UserId][int]NOTNULL,[UserName][varchar](50)NULL,[Password][varchar](50)NOTNULL,CONSTRAINT[PK_Users]PRIMARYKEYCLUSTERED([Id]ASC)WITH(PAD_INDEX=OFF,STATISTICS_NORECOMPUTE=OFF,IGNORE_DUP_KEY=OFF,ALLOW_ROW_LOCKS=ON,ALLOW_PAGE_LOCKS=ON)ON[PRIMARY])ON[PRIMARY]插入一些數(shù)據(jù):INSERTINTO[Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES(NEWID(),1,'name1','pwd1');INSERTINTO[Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES(NEWID(),2,'name2','pwd2');INSERTINTO[Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES(NEWID(),3,'name3','pwd3');INSERTINTO[Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES(NEWID(),4,'name4','pwd4');INSERTINTO[Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES(NEWID(),5,'name5','pwd5');假設(shè)我們有個用戶登錄的頁面,代碼如下:驗(yàn)證用戶登錄的sql如下:selectCOUNT(*)fromUserswherePassword='a'andUserName='b'這段代碼返回Password和UserName都匹配的用戶數(shù)量,如果大于1的話,那么就代表用戶存在。本文不討論SQL中的密碼策略,也不討論代碼規(guī)范,主要是講為什么能夠防止SQL注入,請一些同學(xué)不要糾結(jié)與某些代碼,或者和SQL注入無關(guān)的主題??梢钥吹綀?zhí)行結(jié)果:這個是SQLprofile跟蹤的SQL語句。注入的代碼如下:selectCOUNT(*)fromUserswherePassword='a'andUserName='b'or1=1—'這里有人將UserName設(shè)置為了“b'or1=1–”.實(shí)際執(zhí)行的SQL就變成了如下:可以很明顯的看到SQL注入成功了。很多人都知道參數(shù)化查詢可以避免上面出現(xiàn)的注入問題,比如下面的代碼:classProgram{privatestaticstringconnectionString="DataSource=.;InitialCatalog=Test;IntegratedSecurity=True";staticvoidMain(string[]args){Login("b","a");Login("b'or1=1--","a");}privatestaticvoidLogin(stringuserName,stringpassword){using(SqlConnectionconn=newSqlConnection(connectionString)){conn.Open();SqlCommandcomm=newSqlCommand();comm.Connection=conn;//為每一條數(shù)據(jù)添加一個參數(shù)comm.CommandText="selectCOUNT(*)fromUserswherePassword=@PasswordandUserName=@UserName";comm.Parameters.AddRange(newSqlParameter[]{newSqlParameter("@Password",SqlDbType.VarChar){Value=password},newSqlParameter("@UserName",SqlDbType.VarChar){Value=userName},});comm.ExecuteNonQuery();}}}實(shí)際執(zhí)行的SQL如下所示:execsp_executesqlN'selectCOUNT(*)fromUserswherePassword=@PasswordandUserName=@UserName',N'@Passwordvarchar(1),@UserNamevarchar(1)',@Password='a',@UserName='b'execsp_executesqlN'selectCOUNT(*)fromUserswherePassword=@PasswordandUserName=@UserName',N'@Passwordvarchar(1),@UserNamevarchar(11)',@Password='a',@UserName='b''or1=1—'可以看到參數(shù)化查詢主要做了這些事情:1:參數(shù)過濾,可以看到@UserName='b''or1=1—'2:執(zhí)行計劃重用因?yàn)閳?zhí)行計劃被重用,所以可以防止SQL注入。首先分析SQL注入的本質(zhì),用戶寫了一段SQL用來表示查找密碼是a的,用戶名是b的所有用戶的數(shù)量。通過注入SQL,這段SQL現(xiàn)在表示的含義是查找(密碼是a的,并且用戶名是b的,)或者1=1的所有用戶的數(shù)量。可以看到SQL的語意發(fā)生了改變,為什么發(fā)生了改變呢?,因?yàn)闆]有重用以前的執(zhí)行計劃,因?yàn)閷ψ⑷牒蟮腟QL語句重新進(jìn)行了編譯,因?yàn)橹匦聢?zhí)行了語法解析。所以要保證SQL語義不變,即我想要表達(dá)SQL就是我想表達(dá)的意思,不是別的注入后的意思,就應(yīng)該重用執(zhí)行計劃。如果不能夠重用執(zhí)行計劃,那么就有SQL注入的風(fēng)險,因?yàn)镾QL的語意有可能會變化,所表達(dá)的查詢就可能變化。在SQLServer中查詢執(zhí)行計劃可以使用下面的腳本:DBCCFreeProccacheselecttotal_elapsed_time/execution_count平均時間,total_logical_reads/execution_count邏輯讀,usecounts重用次數(shù),SUBSTRING(d.text,(statement_start_offset/2)+1,((CASEstatement_end_offsetWHEN-1THENDATALENGTH(text)ELSEstatement_end_offsetEND-statement_start_offset)/2)+1)語句執(zhí)行fromsys.dm_exec_cached_plansacrossapplysys.dm_exec_query_plan(a.plan_handle)c,sys.dm_exec_query_statsbcrossapplysys.dm_exec_sql_text(b.sql_handle)d--wherea.plan_handle=b.plan_handleandtotal_logical_reads/execution_count4000ORDERBYtotal_elapsed_time/execution_countDESC;

創(chuàng)新互聯(lián)公司專注于平城企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站建設(shè),商城網(wǎng)站定制開發(fā)。平城網(wǎng)站建設(shè)公司,為平城等地區(qū)提供建站服務(wù)。全流程按需策劃,專業(yè)設(shè)計,全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

sql解析就是sel優(yōu)化么

很多人不知道SQL語句在SQLSERVER中是如何執(zhí)行的,他們擔(dān)心自己所寫的SQL語句會被SQLSERVER誤解。比如:select*fromtable1wherename='zhangsan'andtID10000和執(zhí)行:select*fromtable1wheretID10000andname='zhangsan'一些人不知道以上兩條語句的執(zhí)行效率是否一樣,因?yàn)槿绻唵蔚膹恼Z句先后上看,這兩個語句的確是不一樣,如果tID是一個聚合索引,那么后一句僅僅從表的10000條以后的記錄中查找就行了;而前一句則要先從全表中查找看有幾個name='zhangsan'的,而后再根據(jù)限制條件條件tID10000來提出查詢結(jié)果。事實(shí)上,這樣的擔(dān)心是不必要的。SQLSERVER中有一個“查詢分析優(yōu)化器”,它可以計算出where子句中的搜索條件并確定哪個索引能縮小表掃描的搜索空間,也就是說,它能實(shí)現(xiàn)自動優(yōu)化。雖然查詢優(yōu)化器可以根據(jù)where子句自動的進(jìn)行查詢優(yōu)化,但大家仍然有必要了解一下“查詢優(yōu)化器”的工作原理,如非這樣,有時查詢優(yōu)化器就會不按照您的本意進(jìn)行快速查詢。在查詢分析階段,查詢優(yōu)化器查看查詢的每個階段并決定限制需要掃描的數(shù)據(jù)量是否有用。如果一個階段可以被用作一個掃描參數(shù)(SARG),那么就稱之為可優(yōu)化的,并且可以利用索引快速獲得所需數(shù)據(jù)。SARG的定義:用于限制搜索的一個操作,因?yàn)樗ǔJ侵敢粋€特定的匹配,一個值得范圍內(nèi)的匹配或者兩個以上條件的AND連接。形式如下:列名操作符或操作符列名列名可以出現(xiàn)在操作符的一邊,而常數(shù)或變量出現(xiàn)在操作符的另一邊。如:Name='張三'價格500050005000如果一個表達(dá)式不能滿足SARG的形式,那它就無法限制搜索的范圍了,也就是SQLSERVER必須對每一行都判斷它是否滿足WHERE子句中的所有條件。所以一個索引對于不滿足SARG形式的表達(dá)式來說是無用的。介紹完SARG后,我們來總結(jié)一下使用SARG以及在實(shí)踐中遇到的和某些資料上結(jié)論不同的經(jīng)驗(yàn):1、Like語句是否屬于SARG取決于所使用的通配符的類型--如:namelike'張%'--,這就屬于SARG--而:namelike'%張'--,就不屬于SARG。原因是通配符%在字符串的開通使得索引無法使用。2、or會引起全表掃描Name='張三'and價格5000符號SARG,而:Name='張三'or價格5000則不符合SARG。使用or會引起全表掃描。3、非操作符、函數(shù)引起的不滿足SARG形式的語句不滿足SARG形式的語句最典型的情況就是包括非操作符的語句,如:NOT、!=、、!、NOTEXISTS、NOTIN、NOTLIKE等,另外還有函數(shù)。下面就是幾個不滿足SARG形式的例子:ABS(價格)5000--SQLSERVER也會認(rèn)為是SARG,SQLSERVER會將此式轉(zhuǎn)化為:WHERE價格2500/2但我們不推薦這樣使用,因?yàn)橛袝rSQLSERVER不能保證這種轉(zhuǎn)化與原始表達(dá)式是完全等價的。4、IN的作用相當(dāng)與OR語句:Select*fromtable1wheretidin(2,3)--和Select*fromtable1wheretid=2ortid=3是一樣的,都會引起全表掃描,如果tid上有索引,其索引也會失效。5、盡量少用NOT6、exists和in的執(zhí)行效率是一樣的很多資料上都顯示說,exists要比in的執(zhí)行效率要高,同時應(yīng)盡可能的用notexists來代替notin。但事實(shí)上,我試驗(yàn)了一下,發(fā)現(xiàn)二者無論是前面帶不帶not,二者之間的執(zhí)行效率都是一樣的。因?yàn)樯婕白硬樵?,我們試?yàn)這次用SQLSERVER自帶的pubs數(shù)據(jù)庫。運(yùn)行前我們可以把SQLSERVER的statisticsI/O狀態(tài)打開:(1)selecttitle,pricefromtitleswheretitle_idin(selecttitle_idfromsaleswhereqty30)該句的執(zhí)行結(jié)果為:表'sales'。掃描計數(shù)18,邏輯讀56次,物理讀0次,預(yù)讀0次。表'titles'。掃描計數(shù)1,邏輯讀2次,物理讀0次,預(yù)讀0次。(2)selecttitle,pricefromtitleswhereexists(select*fromsaleswheresales.title_id=titles.title_idandqty30)第二句的執(zhí)行結(jié)果為:表'sales'。掃描計數(shù)18,邏輯讀56次,物理讀0次,預(yù)讀0次。表'titles'。掃描計數(shù)1,邏輯讀2次,物理讀0次,預(yù)讀0次。我們從此可以看到用exists和用in的執(zhí)行效率是一樣的。7、用函數(shù)charindex()和前面加通配符%的LIKE執(zhí)行效率一樣前面,我們談到,如果在LIKE前面加上通配符%,那么將會引起全表掃描,所以其執(zhí)行效率是低下的。但有的資料介紹說,用函數(shù)charindex()來代替LIKE速度會有大的提升,經(jīng)我試驗(yàn),發(fā)現(xiàn)這種說明也是錯誤的:selectgid,title,fariqi,readerfromtgongwen wherecharindex('刑偵支隊(duì)',reader)0andfariqi'2004-5-5'用時:7秒,另外:掃描計數(shù)4,邏輯讀7155次,物理讀0次,預(yù)讀0次。selectgid,title,fariqi,readerfromtgongwen wherereaderlike'%'+'刑偵支隊(duì)'+'%'andfariqi'2004-5-5'用時:7秒,另外:掃描計數(shù)4,邏輯讀7155次,物理讀0次,預(yù)讀0次。8、union并不絕對比or的執(zhí)行效率高我們前面已經(jīng)談到了在where子句中使用or會引起全表掃描,一般的,我所見過的資料都是推薦這里用union來代替or。事實(shí)證明,這種說法對于大部分都是適用的。selectgid,fariqi,neibuyonghu,reader,titlefromTgongwen wherefariqi='2004-9-16'orgid9990000用時:68秒。掃描計數(shù)1,邏輯讀404008次,物理讀283次,預(yù)讀392163次。selectgid,fariqi,neibuyonghu,reader,titlefromTgongwenwherefariqi='2004-9-16'unionselectgid,fariqi,neibuyonghu,reader,titlefromTgongwenwheregid9990000用時:9秒。掃描計數(shù)8,邏輯讀67489次,物理讀216次,預(yù)讀7499次??磥?,用union在通常情況下比用or的效率要高的多。但經(jīng)過試驗(yàn),筆者發(fā)現(xiàn)如果or兩邊的查詢列是一樣的話,那么用union則反倒和用or的執(zhí)行速度差很多,雖然這里union掃描的是索引,而or掃描的是全表。selectgid,fariqi,neibuyonghu,reader,titlefromTgongwen wherefariqi='2004-9-16'orfariqi='2004-2-5'用時:6423毫秒。掃描計數(shù)2,邏輯讀14726次,物理讀1次,預(yù)讀7176次。selectgid,fariqi,neibuyonghu,reader,titlefromTgongwenwherefariqi='2004-9-16'unionselectgid,fariqi,neibuyonghu,reader,titlefromTgongwenwherefariqi='2004-2-5'用時:11640毫秒。掃描計數(shù)8,邏輯讀14806次,物理讀108次,預(yù)讀1144次。9、字段提取要按照“需多少、提多少”的原則,避免“select*”我們來做一個試驗(yàn):selecttop10000gid,fariqi,reader,titlefromtgongwenorderbygiddesc用時:4673毫秒selecttop10000gid,fariqi,titlefromtgongwenorderbygiddesc用時:1376毫秒selecttop10000gid,fariqifromtgongwenorderbygiddesc用時:80毫秒由此看來,我們每少提取一個字段,數(shù)據(jù)的提取速度就會有相應(yīng)的提升。提升的速度還要看您舍棄的字段的大小來判斷。10、count(*)不比count(字段)慢某些資料上說:用*會統(tǒng)計所有列,顯然要比一個世界的列名效率低。這種說法其實(shí)是沒有根據(jù)的。我們來看:selectcount(*)fromTgongwen用時:1500毫秒selectcount(gid)fromTgongwen用時:1483毫秒selectcount(fariqi)fromTgongwen用時:3140毫秒selectcount(title)fromTgongwen用時:52050毫秒從以上可以看出,如果用count(*)和用count(主鍵)的速度是相當(dāng)?shù)?,而count(*)卻比其他任何除主鍵以外的字段匯總速度要快,而且字段越長,匯總的速度就越慢。我想,如果用count(*),SQLSERVER可能會自動查找最小字段來匯總的。當(dāng)然,如果您直接寫count(主鍵)將會來的更直接些。11、orderby按聚集索引列排序效率最高我們來看:(gid是主鍵,fariqi是聚合索引列):selecttop10000gid,fariqi,reader,titlefromtgongwen用時:196毫秒。掃描計數(shù)1,邏輯讀289次,物理讀1次,預(yù)讀1527次。selecttop10000gid,fariqi,reader,titlefromtgongwenorderbygidasc用時:4720毫秒。掃描計數(shù)1,邏輯讀41956次,物理讀0次,預(yù)讀1287次。selecttop10000gid,fariqi,reader,titlefromtgongwenorderbygiddesc用時:4736毫秒。掃描計數(shù)1,邏輯讀55350次,物理讀10次,預(yù)讀775次。selecttop10000gid,fariqi,reader,titlefromtgongwenorderbyfariqiasc用時:173毫秒。掃描計數(shù)1,邏輯讀290次,物理讀0次,預(yù)讀0次。selecttop10000gid,fariqi,reader,titlefromtgongwenorderbyfariqidesc用時:156毫秒。掃描計數(shù)1,邏輯讀289次,物理讀0次,預(yù)讀0次。從以上我們可以看出,不排序的速度以及邏輯讀次數(shù)都是和“orderby聚集索引列”的速度是相當(dāng)?shù)模@些都比“orderby非聚集索引列”的查詢速度是快得多的。同時,按照某個字段進(jìn)行排序的時候,無論是正序還是倒序,速度是基本相當(dāng)?shù)摹?2、高效的TOP事實(shí)上,在查詢和提取超大容量的數(shù)據(jù)集時,影響數(shù)據(jù)庫響應(yīng)時間的最大因素不是數(shù)據(jù)查找,而是物理的I/0操作。如:selecttop10*from(selecttop10000gid,fariqi,titlefromtgongwenwhereneibuyonghu='公室'orderbygiddesc)asaorderbygidasc這條語句,從理論上講,整條語句的執(zhí)行時間應(yīng)該比子句的執(zhí)行時間長,但事實(shí)相反。因?yàn)?,子句?zhí)行后返回的是10000條記錄,而整條語句僅返回10條語句,所以影響數(shù)據(jù)庫響應(yīng)時間最大的因素是物理I/O操作。而限制物理I/O操作此處的最有效方法之一就是使用TOP關(guān)鍵詞了。TOP關(guān)鍵詞是SQLSERVER中經(jīng)過系統(tǒng)優(yōu)化過的一個用來提取前幾條或前幾個百分比數(shù)據(jù)的詞。經(jīng)筆者在實(shí)踐中的應(yīng)用,發(fā)現(xiàn)TOP確實(shí)很好用,效率也很高。但這個詞在另外一個大型數(shù)據(jù)庫ORACLE中卻沒有,這不能說不是一個遺憾,雖然在ORACLE中可以用其他方法(如:rownumber)來解決。在以后的關(guān)于“實(shí)現(xiàn)千萬級數(shù)據(jù)的分頁顯示存儲過程”的討論中,我們就將用到TOP這個關(guān)鍵詞。到此為止,我們上面討論了如何實(shí)現(xiàn)從大容量的數(shù)據(jù)庫中快速地查詢出您所需要的數(shù)據(jù)方法。當(dāng)然,我們介紹的這些方法都是“軟”方法,在實(shí)踐中,我們還要考慮各種“硬”因素,如:網(wǎng)絡(luò)性能、服務(wù)器的性能、操作系統(tǒng)的性能,甚至網(wǎng)卡、交換機(jī)等。

如何查看sqlserver執(zhí)行計劃來判斷SQL語句效率

通過對執(zhí)行計劃的跟蹤,確定邏輯讀最多最亂的,從索引入手解決。

再次跟蹤,發(fā)現(xiàn)其在執(zhí)行過程中占用資源最大的百分比,然后分析表的連接。

關(guān)于SQL SERVER優(yōu)化,是個長期學(xué)習(xí)的過程,基本的優(yōu)化含有了索引等內(nèi)容,但深入優(yōu)化就需要掌握更多的存儲引擎方面的知識了。建議學(xué)習(xí)官方書籍《SQL SERVER2008存儲引擎》


網(wǎng)站名稱:sqlserver邏輯讀,sql思維
網(wǎng)頁網(wǎng)址:http://weahome.cn/article/hdjscc.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部