最近讀了 程序員的SQL金典 這本書,覺得里面的SQL注入漏洞和SQL調優總結得不錯,下面簡單討論下SQL注入漏洞和SQL調優。
1.?SQL 注入漏洞
由于“ '1'='1' ”這個表達式永遠返回? true ,而? true? 與任何布爾值的? or? 運算的結果都是? true ,那么無論正確密碼是什么“ Password='1'?or?'1'='1' ”的計算值永遠是? true ,這樣惡意攻擊者就可以使用任何帳戶登錄系統了。這樣的漏洞就被稱作“ SQL? 注入漏洞( SQL?Injection )”。
對付? SQL? 注入漏洞有兩種方式:過濾敏感字符和使用參數化? SQL 。?
1). 過濾敏感字符
過濾敏感字符的思路非常簡單,由于惡意攻擊者一般需要在輸入框中輸入的文本一般含有? or 、 and 、 select 、 delete? 之類的字符串片段,所以在拼接? SQL? 之前檢查用戶提交的文本中是否含有這些敏感字符串,如果含有則終止操作。
2).使用參數化 SQL
為運行時才能確定的用戶名和密碼設置了占位符,然后在運行時再設定占位符的值,在執行時? Java 、 C# 會直接將參數化? SQL? 以及對應的參數值傳遞給? DBMS ,在? DBMS? 中會將參數值當成一個普通的值來處理而不是將它們拼接到參數化? SQL? 中 ,因此從根本上避免了? SQL? 注入漏洞攻擊。
?
2.?SQL? 調優?
在使用? DBMS? 時經常對系統的性能有非常高的要求:不能占用過多的系統內存和 CPU? 資源、要盡可能快的完成的數據庫操作、要有盡可能高的系統吞吐量。如果系統開發出來不能滿足要求的所有性能指標,則必須對系統進行調整,這個工作被稱為調優。
SQL? 調優的基本原則???
“二八原理”是一個普遍的真理,特別是在計算機的世界中表現的更加明顯,那就是? 20% 的代碼的資源消耗占用了? 80% 的總資源消耗。 SQL? 語句也是一種代碼,因此它也符合這個原理。在進行? SQL? 調優的時候應該把主要精力放到這? 20% 的最消耗系統資源的? SQL? 語句中,不要想把所有的? SQL? 語句都調整到最優狀態。???
索引是數據庫調優的最根本的優化方法。
常用的 SQL 調優方法:
1)? 創建必要的索引
2)?使用預編譯查詢?
程序中通常是根據用戶的輸入來動態執行? SQL? 語句,這時應該盡量使用參數化 SQL ,這樣不僅可以避免? SQL? 注入漏洞攻擊,最重要數據庫會對這些參數化? SQL? 執行預編譯。
3)?調整? WHERE? 子句中的連接順序?
DBMS? 一般采用自下而上的順序解析? WHERE? 子句,根據這個原理 , 表連接最好寫在其他? WHERE? 條件之前,那些可以過濾掉最大數量記錄。?
比如下面的? SQL? 語句性能較差:? SELECT?*???FROM?T_Person?WHERE???FSalary?>?50000??AND?????FPosition=? ‘ MANAGER ’?? AND?????25?<?(SELECT?COUNT(*)?FROM?T_Manager?WHERE?FManagerId=2);??
我們將子查詢的條件放到最前面,下面的? SQL? 語句性能比較好:? SELECT?*???FROM?T_Person?WHERE???25?<?(SELECT?COUNT(*)?FROM?T_Manager?WHERE?FManagerId=2)?AND?FSalary?>?50000??AND?????FPosition=? ‘ MANAGER ’? ;?
4)?SELECT? 語句中避免使用 '*'?
SELECT??* 比較簡單,但是除非確實需要檢索所有的列,否則將會檢索出不需要的列,這回增加網絡的負載和服務器的資源消耗;即使確實需要檢索所有列,也不要使用 SELECT?* ,因為這是一個非常低效的方法, DBMS? 在解析的過程中,會將 * 依次轉換成所有的列名,這意味著將耗費更多的時間。
5)?盡量將多條? SQL? 語句壓縮到一句? SQL? 中
每次執行? SQL? 的時候都要建立網絡連接、進行權限校驗、進行? SQL? 語句的查詢優化、發送執行結果,這個過程是非常耗時的,因此應該盡量避免過多的執行? SQL? 語句,能夠壓縮到一句? SQL? 執行的語句就不要用多條來執行。
6)?用? Where? 子句替換? HAVING? 子句??
避免使用? HAVING? 子句,因為? HAVING?? 只會在檢索出所有記錄之后才對結果集進行過濾。如果能通過? WHERE? 子句限制記錄的數目,那就能減少這方面的開銷。 HAVING?? 中的條件一般用于聚合函數的過濾,除此而外,應該將條件寫在? WHERE? 子句中。?
7)?使用表的別名?
當在? SQL? 語句中連接多個表時,請使用表的別名并把別名前綴于每個列名上。這樣就可以減少解析的時間并減少那些由列名歧義引起的語法錯誤。?
8)?用? EXISTS? 替代? IN??
在查詢中,為了滿足一個條件,往往需要對另一個表進行聯接,在這種情況下,使用? EXISTS? 而不是? IN? 通常將提高查詢的效率,因為? IN? 子句將執行一個子查詢內部的排序和合并。
9)?用表連接替換? EXISTS???
通常來說,表連接的方式比? EXISTS? 更有效率,因此如果可能的話盡量使用表連接替換? EXISTS 。
10)?避免在索引列上使用計算?
在? WHERE? 子句中,如果索引列是計算或者函數的一部分, DBMS? 的優化器將不會使用索引而使用全表掃描。
11)?用? UNION?ALL?? 替換? UNION??
當? SQL? 語句需要? UNION? 兩個查詢結果集合時,即使檢索結果中不會有重復的記錄,如果使用? UNION? 這兩個結果集同樣會嘗試進行合并,然后在輸出最終結果前進行排序。?因此,如果檢索結果中不會有重復的記錄的話,應該用? UNION?ALL? 替代? UNION ,這樣效率就會因此得到提高。
12)?避免隱式類型轉換造成的全表掃描?
13)?防止檢索范圍過寬???
如果? DBMS? 優化器認為檢索范圍過寬,那么它將放棄索引查找而使用全表掃描。下面是幾種可能造成檢索范圍過寬的情況:?使用? IS?NOT?NULL? 或者不等于判斷,可能造成優化器假設匹配的記錄數太多。?使用? LIKE? 運算符的時候, "a%" 將會使用索引,而 "a%c" 和 "%c" 則會使用全表掃描,因此 "a%c" 和 "%c" 不能被有效的評估匹配的數量。?
如果您有什么問題,歡迎在下面評論,我們一起討論,謝謝~
如果您覺得還不錯,不妨點下右下方的推薦,有您的鼓勵我會繼續努力的~
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
