SQL查找是否"存在",別再用count了
根據(jù)某一條件從數(shù)據(jù)庫(kù)表中查詢『有』與『沒(méi)有』,只有兩種狀態(tài),那為什么在寫(xiě) SQL 的時(shí)候,還要 SELECT COUNT(*) 呢?
圖片來(lái)自 Pexels
無(wú)論是剛?cè)氲赖某绦騿T新星,還是精湛沙場(chǎng)多年的程序員老白,都是一如既往的 COUNT。
目前多數(shù)人的寫(xiě)法
多次 REVIEW 代碼時(shí),發(fā)現(xiàn)如現(xiàn)現(xiàn)象:業(yè)務(wù)代碼中,需要根據(jù)一個(gè)或多個(gè)條件,查詢是否存在記錄,不關(guān)心有多少條記錄。
普遍的 SQL 及代碼寫(xiě)法如下:
- ##### SQL寫(xiě)法:
- SELECT count(*) FROM table WHERE a = 1 AND b = 2
- ##### Java寫(xiě)法:
- int nums = xxDao.countXxxxByXxx(params);
- if ( nums > 0 ) {
- //當(dāng)存在時(shí),執(zhí)行這里的代碼
- } else {
- //當(dāng)不存在時(shí),執(zhí)行這里的代碼
- }
是不是感覺(jué)很 OK,沒(méi)有什么問(wèn)題?
優(yōu)化方案
推薦寫(xiě)法如下:
- ##### SQL寫(xiě)法:
- SELECT 1 FROM table WHERE a = 1 AND b = 2 LIMIT 1
- ##### Java寫(xiě)法:
- Integer exist = xxDao.existXxxxByXxx(params);
- if ( exist != NULL ) {
- //當(dāng)存在時(shí),執(zhí)行這里的代碼
- } else {
- //當(dāng)不存在時(shí),執(zhí)行這里的代碼
- }
SQL 不再使用 COUNT,而是改用 LIMIT 1,讓數(shù)據(jù)庫(kù)查詢時(shí)遇到一條就返回,不要再繼續(xù)查找還有多少條了。
業(yè)務(wù)代碼中直接判斷是否非空即可!
根據(jù)查詢條件查出來(lái)的條數(shù)越多,性能提升的越明顯,在某些情況下,還可以減少聯(lián)合索引的創(chuàng)建。
總結(jié)
COUNT() 有兩個(gè)非常不同的作用:
它可以統(tǒng)計(jì)某個(gè)列值的數(shù)量,也可以統(tǒng)計(jì)行數(shù)。在統(tǒng)計(jì)列值時(shí)要求列值是非空的(不統(tǒng)計(jì) NULL)。
如果在 COUNT() 的括號(hào)中定了列或者列表達(dá)式,則統(tǒng)計(jì)的就是這個(gè)表達(dá)式有值的結(jié)果數(shù)。......COUNT() 的另一個(gè)作用是統(tǒng)計(jì)結(jié)果集的行數(shù)。當(dāng) MySQL 確認(rèn)括號(hào)內(nèi)的表達(dá)式值不可能為空時(shí),實(shí)際上就是在統(tǒng)計(jì)行數(shù)。
最簡(jiǎn)單的就是當(dāng)我們使用 COUNT(*) 的時(shí)候,這種情況下通配符 * 并不像我們猜想的那樣擴(kuò)展成所有的列,實(shí)際上,他會(huì)忽略所有列而直接統(tǒng)計(jì)所有的行數(shù)。
——《高性能MySQL》
不管怎樣,我們判斷是否存在。只需確定,有和無(wú),而不是,無(wú)還是有多少!在有的情況下,直接返回,而不需要繼續(xù)統(tǒng)計(jì)行數(shù)!
巧妙的使用 LIMIT 1,獲得更高效率,尤其是在某些復(fù)雜且不規(guī)范的語(yǔ)句中效果更明顯!
作者:程序猿囧途
編輯:陶家龍
出處:toutiao.com/i6826511837840802315