CPU瓶頸(二) 過度的查詢語句編譯及優化

2021-06-05 22:18:13 字數 1711 閱讀 9854

查詢語句編譯及優化是一項cpu密集處理操作。查詢語句優化的花費會因為語句的複雜性及基礎架構的增長而增加,但是即使是乙個非常簡單的查詢語句也可以花費cpu10-20毫秒的時間去解析和編譯。

為了減緩這種花費,sql server快取並且重用已經編譯過的查詢計畫。每次從客戶端接收到乙個新的查詢語句時,sql server首先從計畫快取(有些時候被叫做過程快取)中查詢是否存在乙個編譯過的計畫可被重複使用。如果找不到乙個匹配的查詢計畫,sql server會將傳進來的查詢語句進行解析和辨析,然後才執行它。

sql injection

using sp_executesql

診斷

在編譯期間,sql server 2008 為查詢語句生成了乙個「證書」並且顯示在sys.dm_exec_requestssys.dm_exec_query_statsquery_hash列中,並且作為query_hash屬性存在於showplan/statistics xml文件中。對於已經寫進了query_hash引數化格式的實體,如果具有相同的query_hash,它們很可能涉及到相同的查詢文字。對於只是文字本身不一樣的查詢,它們擁有相同的query_hash值。例如,前兩個查詢共享同乙個query hash, 然而第三個有不同的query hash,因為它執行的是不同的操作:

select * from sys.objects where object_id = 100

select * from sys.objects where object_id = 101

select * from sys.objects where name = 'sysobjects'

query hash 產生於編譯期間的樹形結構。空白會被忽略掉,因為在select 語句中使用 * 和 使用多個列名,差別還是很大的。此外,如果乙個查詢語句使用全名而另乙個查詢語句只是使用table名,但是它們對應於同乙個物件,這種情況是沒有關係的。下面所有的語句將會使用同乙個query_hash。

use adventureworks

goset showplan_xml on

goselect * from saleorderheader h

select * from sales.salesorderheader h

select salesorderid,..., modifieddate from sales.salesorderheader h

goset showplan_xml off

go請注意在query_hash值生成的時候,資料庫名稱部分在全名中被忽略掉了。這樣做允許資源在instance上的所有資料庫中進行使用。

為了去診斷應用程式提交過來了多個即時查詢語句,乙個簡單的方法是按照sys.dm_exec_query_stats.query_hash列進行分組,如下:

對於那些number_of_enties列中的值在幾百甚至幾千的查詢語句,它們是設定引數化的最好物件。如果你檢視xml查詢計畫中tag下的compiletime及complilecpu屬性,並且將這些value與number_of_entries的值相乘,你會得到乙個估計值,這也就是如果你使用引數化,會有多少編譯時間和cpu被消除(這也就意味著查詢語句被編譯了一次,然後它被快取並且後來被重複執行)。消除這些不需要的快取計畫可以帶來一些意想不到的好處,比如釋放記憶體去快取其它的便已計畫(從而更深層次減少編譯開支)並且留出更多的記憶體空間給快取。

查詢CPU占用高的SQL語句

注意 sql server中查詢cpu占用高的情況,經常會用到sys.sysprocesses dm exec sessions dm exec requests 1 檢視當前的資料庫使用者連線數 use master goselect from sys.sysprocesses where spi...

第二高的薪水(SQL查詢語句)

編寫乙個 sql 查詢,獲取employee表中第二高的薪水 salary id salary 1 100 2 200 3 300 例如上述employee表,sql查詢應該返回200作為第二高的薪水。如果不存在第二高的薪水,那麼查詢應返回null。secondhighestsalary 200 答...

PHP中對mysql預編譯查詢語句的乙個封裝

為了防止sql注入,我們都使用過mysqli這個類,但是每次都需要繫結引數,繫結結果等,比較麻煩,所以可以把這些重複的語句封裝成乙個函式.一.封裝前.傳統的乙個預編譯方式的 select 查詢 id 1 name test name db obj new mysqli localhost db us...