{eval=Array;=+count(Array);}
看了下面各位的回答,有的說用exist,有的說用join,難道你們不是在把簡單的事情復雜化了嗎?竟然還有子表子查詢一說?也有朋友說的很精準,不要用select *,這個*是個坑,實際開發(fā)過程中,關于MySQL開發(fā)規(guī)范也會明確告知大家不要select *。
首先我想問的是:查詢MySQL的一張表怎么查最快?當然是根據(jù)主鍵查詢了!
默認你的MySQL庫、表引擎是Innodb引擎,然后會有一顆主鍵的B+樹,葉子節(jié)點就是這個主鍵索引對應的數(shù)據(jù),意味著一次查詢即可,回表都不需要好不好?簡單直接!
這就是MySQL在Innodb引擎下的聚集索引。
InnoDB聚集索引的葉子節(jié)點存儲行記錄,因此InnoDB必須要有且只有一個聚集索引。
1.如果表定義了PK(Primary Key,主鍵),那么PK就是聚集索引。
2.如果表沒有定義PK,則第一個NOT NULL UNIQUE的列就是聚集索引。
3.否則InnoDB會另外創(chuàng)建一個隱藏的ROWID作為聚集索引。
這種機制使得基于PK的查詢速度非常快,因為直接定位的行記錄。
下圖是利用普通索引做查詢時候的一個回表操作,如何避免回表操作?使用覆蓋索引!即select xxx,yyy from table where xxx=' and yyy=',只能查詢xxx,yyy就會避免回表操作!
所以你還搞什么其他各種操作來秀呢?只不過題主說了id不是連續(xù)的,所以做不到范圍查詢,也就無法between查詢了。
如果這個查詢量級很大,并發(fā)很高,原則上我們是不允許直接查庫的,中間必須有一層緩存,比如Redis。那至于這個數(shù)據(jù)怎么存儲到redis就要看具體業(yè)務具體分析了。
如果內(nèi)存足夠,甚至可以把這幾十萬的數(shù)據(jù)直接放到redis里面去,然后通過redis 的管道查詢一次給批量查詢出來。
如果沒必要存儲這么多,或者不讓存這么多,是不是可以采用redis的淘汰策略來控制緩存里的數(shù)據(jù)都是熱點數(shù)據(jù)?
select a.* from tableA a
inner join (select id from tableB)b on a. id=b. id
創(chuàng)建臨時表tableB并建主鍵索引,
或者構(gòu)建inner join的只包括id字段的虛擬表b。
mysql8.0版本中有with公共表達式,這個是最好的,通過兩個表做關聯(lián),8.0以下的取決于你的where條件了,icp可以謂詞下推,in在優(yōu)化器會自動轉(zhuǎn)換成semi-jion,在8.0.4以后exists也可以使用semi join了,在之前的時候exists就只能使用dependent subquey了,exists 要想快的話是 小表驅(qū)動大表;所以說這里最重要的是看你的where條件中是否有篩選。如果沒有的話,最好建臨時表 或者用with,另外不要用select *,要不然在后面優(yōu)化器 需要block nestloop的時候會有壓力,如果都不讓用的話,你目前的敘述,in比exists好
MySQL官網(wǎng)有對in的說法,如果有索引,其實都差不多。如果你查詢的不是所有字段,只拿abc三個字段,可以在abc三個字段建立組合索引,in再走索引。如果我沒有記錯MySQL不會限制你in多少,但是會限制整個SQL總字節(jié)數(shù)
1,去掉*, select table.name,table.age,table.asscess from table where in ( ....)
2.如果id是連續(xù)的范圍,那就用between and 代替in
幾十萬行,in還有幾百上千,應該還有一層關系,按歸類給id做排序索引,使得你要的是其中幾段:也即,隨機io轉(zhuǎn)連續(xù)io,再加索引覆蓋。
0
回答0
回答0
回答0
回答0
回答0
回答0
回答0
回答0
回答0
回答