淺析盡量不用count(*)來判斷是否有數據、判斷記錄是否存在 exists 和 top 1 要比 count 快


一、問題描述

  首先說一下,判斷表里是否有記錄,常見的寫法(偽代碼)

-- 定義變量a 
a = (select count(*) from tb) if a > 0 ... else ...

  這么寫是沒錯,看上去也好理解,就是統計一下tb表中的記錄數,然后判斷這個記錄數是否大於0。可能絕大多數人在實現這個需求的時候,都會這么寫。

  接下來,想想這個語句在執行時,會做什么處理:

1、如果tb表沒索引,那么會有表掃描,如果表中的記錄數很大,這個操作會很慢。

2、如果tb表有索引,那么會有索引掃描操作,計算索引記錄有多少條。同樣的,如果記錄數很大,這個操作不會太快,但肯定比第1種情況要快的多。

  那么,有沒有更好的辦法,來實現這個需求呢?

二、優化方案

  這里先想想這個需求本身,就是要判斷tb表中是否有記錄。上面這句話的意思很明確,仔細想想,判斷結果是:要么有,要么沒有,而至於表中到底有多少條記錄,這種精確的信息,他是不關注的。所以,我們可以朝着這個方向去優化,我想到的辦法有2個:

1、exists

a = case when exists(select id from tb) then 1 else 0 end

2、返回1條記錄

-- 方式1
a = (select count(1) from tb where rownum=1) -- 方式2
a = (select count(1) from (select top 1 id from tb ) t) 

3、兩種方法的對比

  上面的2種改進的寫法,雖然具體的實現方式不一樣,一個是用 exists,一個是用 top 或 rownum 來限制返回1條記錄,但意思是相同的,就是只看表里是否有記錄,不關注記錄數。

  就這么一個簡單的需求,實現起來雖然很簡單,但是,如果不好好想想,深入理解需求的本質,恐怕也不容易有個好的實現(這里的“實現”兩字,表示把需求轉化為代碼的過程),更何況其他更加復雜的需求。

三、判斷記錄是否存在: exists 和 top 1 要比 count 快

  之前在程序中驗證記錄是否存在,總是用 select count(0) from table1 得到記錄數,然后在比對,思考有沒有性能更好的辦法。

  思考 count 的工作原理后感覺是讀取所有數據后進行統計的,而使用 top 1 會不會只是取得第一個紀錄后就跳出查詢呢?

  正好手頭上有朋友上次做實驗制作的一個300萬記錄的表,我就用來做了下實驗

select count(0) from table1 -- 執行時間 兩次分別是 3秒,1秒

select top 1 0 from table1 -- 兩次執行時間都為0秒

exists( select  0 from table1) -- 兩次都為0秒

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM