2017-07-18 155 views
-1

假設我們有一個表員工。我在這個表上執行2個以下的查詢。爲什麼在oracle SQL中執行具有兩個不同值的查詢所花費的時間相差很多

查詢1

select * from employee where email_id = '[email protected]' 

查詢2

select * from employee where email_id = '[email protected]' 

假設我有上我執行此查詢一個巨大的數據集。觀察結果是Query1比Query2花費的時間少得多。我也檢查了列email_id沒有索引。我的假設是服務器以某種方式緩存Query1而不是Query2。如果這是真的,那我該如何強制服務器緩存Query2?另外,如果可能的話,我希望不使用索引來優化Query2。有什麼建議麼?

回答

1

如果沒有email_id的索引,我們預計這兩個查詢都將花費同一時間,即在employees表上執行全表掃描所需的時間。那麼爲什麼一個查詢返回比另一個快得多呢?

假設:

  1. 你真正的查詢使用硬編碼值而不是綁定變量(即select * from employee where email_id = ':1')。
  2. 更具表現性的查詢確實在搜索admin電子郵件地址。

包含文字的查詢通常是一件壞事:每個版本都必須進行硬解析,它們會佔用遊標緩存中的空間。但是他們也可能有不同的執行路徑(因爲它們被單獨解析)或性能配置文件。這似乎就是這種情況。如果沒有索引,訪問路徑將是相同的,但由於緩存的原因,總的使用時間可能會有所不同。

有兩種可能的緩存可能在使用。

  1. 意外緩存。包含employee[email protected]記錄的塊已經在DB緩衝區緩存中,因此查詢不必讀取整個表。
  2. 蓄意緩存。有些人通過電子郵件地址查詢僱員,其中使用resultset caching,並且[email protected]employee記錄被緩存在那裏。

因此,可以緩存[email protected]的兩個原因。顯然,任何員工都可能會這樣。但似乎人們可能會比[email protected]更頻繁地尋找[email protected]。很簡單,(不知道您的應用程序或數據),管理員用戶會被頻繁查詢,因此比任何其他隨機用戶更可能在緩存中。

「我該如何強制服務器緩存Query2?」

如果admin用戶意外緩存 - 因爲它質疑如此頻繁的緩衝它只是保持溫暖 - 有真的沒有什麼可以做。確實,我們可以在內存中添加表格,但這通常是一個糟糕的主意。大多數情況下,數據庫比我們的資源管理更好:如果數據塊沒有保存在數據庫緩衝區緩存中,這是因爲它們不經常使用(假設DBC的大小正確)。

如果您的應用程序正在使用結果集緩存,那麼您可以顯式檢索[email protected]的記錄。但是你不能爲所有的用戶這麼做,出於和以前一樣的原因:如果你經常使用它們,你不想把記錄固定在內存中。

這將我們帶入目標。你想在這裏優化什麼?一個子集的訪問時間/或任何用戶的訪問時間?如果是後者,那麼您需要email_id上的索引。

+0

謝謝你提及許多方法的優點和缺點。我反對索引的原因是我想優化一部分用戶的查詢。 – FTW

0

更多的假設:

  1. 一旦運行QUERY2,它會在你的緩存,並運行它的第二次,你將有一個高速緩存命中,除非你很久以後運行查詢,它有這時已經過時了。
  2. 您正在使用強制系統綁定的cursor_sharing = FORCE
  3. 您有一些非常好的理由不使用email_id上的索引。你真的很想好好利用索引。
  4. 未來,query3和query4等等呢?
+0

我在通過問題8- |完成之前意外按下了'enter' – APC

+1

我按下輸入的目的:)很好的答案APC。我upvoted。 – sandman

相關問題