java的for循环取出数据只是拿到最后一个_一问SQL优化就无从藏身?那只是你对原理的精髓掌握不深
?曾幾何時,我信誓旦旦的認為只要 SQL 寫的好,面試過程永不倒。結(jié)果在一次又一次的征途中,「最終還是以完敗落下帷幕」。
結(jié)果都源于注重使用而忽略原理,從而不知也不了解「SQL」優(yōu)化應(yīng)如何面對。讀文的你,如今可有這樣的滄桑?
1、SQL 執(zhí)行原理過程分析
「話說開篇就談 SQL 的執(zhí)行原理,不太好吧!」
「錯,那是你 矮了,心胸狹隘了」。這都是優(yōu)化的根基呀,SQL 語句最終落地執(zhí)行的場景如果都不明白,那根本就能擁有優(yōu)化的思路。那 SQL 優(yōu)化的定義是什么?
「簡單點,就是以最快的時間獲取到需要的結(jié)果。那怎么快?如何快?」
首先來看看 「MySQL」 檢索數(shù)據(jù)原理過程。例:select * from table id > 5 and name = 'zhazha'
假如。ID 為「主鍵索引」,那么 SQL 執(zhí)行過程可分為兩步:
- 優(yōu)化器調(diào)用存儲引擎提供的 API 接口,通過主鍵索引搜索 ID > 5 的記錄,讀取并載入到 MySQL 服務(wù)層內(nèi)部(即內(nèi)存)
- 在服務(wù)層中,獲取的記錄要一一和 name 字段進行對比。一旦記錄滿足條件就開始逐步發(fā)送給客戶端。每一性的結(jié)果集都通過 MySQL 協(xié)議進行封包,并寫入緩存區(qū),然后再批量傳輸。
故此 「SQL 優(yōu)化」 提速應(yīng)從三方面入手:
- 「掃描的行數(shù),使用索引減少掃描行記錄」
- 「返回的行數(shù),通過 where 條件減少不必要行的判斷。一般 MySQL 有三種應(yīng)用 where 條件」
- ps: 指定 where 條件字段為 索引列,針對聚集索引這種情況
- 在索引中使用 where 條件來過濾不匹配的記錄。這是在存儲引擎層完成的。
- 使用索引覆蓋掃描(在 Extra 列中出現(xiàn) Using index 情況)來返回記錄,直接從索引中過濾不需要的記錄并返回命中的結(jié)果。where 條件將在 MySQL 服務(wù)器層完成,但無須再回表查詢記錄。
- 從數(shù)據(jù)表中返回數(shù)據(jù),然后過濾不滿足條件的記錄(在 Extra 列中出現(xiàn) Using Where)。where 條件將在 MySQL 服務(wù)器層 完成,MySQL 需先從數(shù)據(jù)表讀出記錄然后過濾。
在這里,條件的選擇,將決定服務(wù)器層過濾多少數(shù)據(jù)。
比如:用戶表有 10000 條記錄,每個用戶的 「email」 是唯一的,如果用戶使用 「email」 作為用戶名登陸的話,大多數(shù)可能會這些寫。
但上面的語句實現(xiàn)了查詢 email 對應(yīng)的用戶信息,但由于 email 這一列沒有加索引,會導致全表掃描。然后在服務(wù)層里面再進行 where 條件的一一對比。如何改呢?
SELECT * FROM t_user WHERE email=? LIMIT 1;加上 LIMIT 1,只要找到了對應(yīng)的一條記錄,就不會繼續(xù)向下掃描。
所以在寫 SQL 條件語句時,可查看針會對多少數(shù)據(jù)結(jié)果集。
- 「響應(yīng)時間,即服務(wù)時間和排隊的時間。像 I/O 執(zhí)行、鎖等待消耗的時間」
可似 我還是有幾個疑問?就下面
- 數(shù)據(jù)庫響應(yīng)為什么要一條條結(jié)果發(fā)送呢?不是一起批量響應(yīng)結(jié)果更為方便嗎?結(jié)果集以每條記錄發(fā)送,后面又怎么成為批量傳輸了?
- 那如果是 join 怎么執(zhí)行的呀?SQL 語句怎么來呢?
騷年,就你這個發(fā)問,真乃骨骼驚奇、萬中挑一的編程奇才。實力雄厚這門東西,都是指日可待。到這里是不是應(yīng)該來個贊呢?
「數(shù)據(jù)庫傳輸問題:」MySQL 逐步返回結(jié)果有兩個好處:
- 服務(wù)器端無須存儲太多結(jié)果,也就不會因為要返回太多結(jié)果而 消耗太多內(nèi)存。
- 這樣的處理也讓 MySQL 客戶端第一時間獲的返回的結(jié)果。
「數(shù)據(jù)批量傳輸:」主要因為 MySQL 協(xié)議采用 TCP 協(xié)議傳輸,而 TCP 是一個流式協(xié)議傳輸,類似于你打開水龍頭后,水就一直流出來。
所以數(shù)據(jù)發(fā)送前都會先寫入到網(wǎng)卡的緩沖區(qū)里面,滿了之后才會一并的發(fā)給客戶端。而 MySQL 協(xié)議封包,為的就是防止數(shù)據(jù)出現(xiàn)丟或和數(shù)據(jù)不一致問題。
「join 查詢問題:」
首先我們得明白數(shù)據(jù)庫是如何進行關(guān)聯(lián)查找,對于聯(lián)合查詢,MySQL 先將一系列的單個查詢結(jié)果放到一個臨時表中,然后再重新讀出臨時表數(shù)據(jù)來完成聯(lián)合查詢。
「注:以 關(guān)聯(lián)表 和 主表 說明,當前表 為查詢的主表,關(guān)聯(lián)表為 join 連接的表」
MySQL 先根據(jù) where 條件在主表中找到滿足條件的記錄,然后循環(huán)取出單條數(shù)據(jù),并嵌套循環(huán)到下一個表中尋找匹配的行,依次下去,直到找到所有關(guān)聯(lián)表中匹配的行為止。然后根據(jù)各個表匹配到的行,返回查詢中需要的各個列。
MySQL 會嘗試在最后一個關(guān)聯(lián)表中找到所有匹配的行,如果最后一個關(guān)聯(lián)表無法找到更多的行,MySQL 就返回到上一層次關(guān)聯(lián)表,看是否能夠找到更多的匹配記錄,依此類推迭代執(zhí)行。
注:在 MySQL 的概念中,每個查詢都是一次關(guān)聯(lián)。所以讀取結(jié)果臨時表也是一次關(guān)聯(lián)。
綜上,關(guān)聯(lián)查詢實際就是一個分解查詢的關(guān)系,用主表關(guān)聯(lián)字段的只做為條件,去找到關(guān)聯(lián)表中滿足數(shù)條件得數(shù)據(jù)。
這也是為什么要 join 字段上建立索引的原因,像什么 「order by limit group by」等函數(shù),實際上都是在拿到每個查詢結(jié)果集之后或者之前在索引里面行處理。你所寫的條件,會根據(jù)表的執(zhí)行順序來進行使用,但有時優(yōu)化器會更改執(zhí)行順序。
但我想給關(guān)聯(lián)表加入限制條件呢?
你直接在 on 字段后面 用邏輯連接符號,加入 where 即可。例下:
ON a.id = b.id and b.name = '吒吒輝'
2、前方高能預(yù)警,怎么優(yōu)化 SQL,這方向怎么選?
到現(xiàn)在,大家應(yīng)該對 SQL 優(yōu)化有了屬于自己的側(cè)重點吧。根據(jù)業(yè)務(wù)定位到時間消耗最大并優(yōu)化,試問,這樣你還不能寫出符合你業(yè)務(wù)的語句嗎?
?
在這里請給我來一個點贊和關(guān)注吧,救救在下吧
?
首先定位到某些業(yè)務(wù)查詢很慢,然后再拆解到底是哪個部分最耗時間。
響應(yīng)時間
上面談到,響應(yīng)時間=服務(wù)時間+排隊時間。
- 服務(wù)時間是指數(shù)據(jù)庫處理這個查詢真正花了多長時間。
- 排隊時間是指服務(wù)器因為等待某些資源而沒有真正執(zhí)行查詢的時間。可能是等 I/O 操作完成,也可能是等待行鎖一般最常見和重要的等待是 I/O 和鎖等待,但是實際情況更加復雜,你免 SQL 語句中的執(zhí)行函數(shù)和其它內(nèi)存上的分配等等吧。
所以針對一個查詢很慢語句,首先得看這個語句是查詢上的問題還是服務(wù)器的問題。如果是查詢語句慢,那你優(yōu)化 SQ 語句。如果是服務(wù)器上整體程序都比較慢,大多數(shù)都是服務(wù)器負責太高。
那要怎么做呢?
- 使用 SHOW GLOBAL STATUS
通過 SHOW GLOBAL STATUS查看每秒的查詢數(shù)(Queries)、Threads* connected 和 Threads* running (表示當前正在執(zhí)行查詢的線程數(shù))。
進而定位 mysql 工作線程是否達到瓶頸。
這三個數(shù)據(jù)的趨勢對于服務(wù)器級別偶爾停頓的敏感性很高。一般發(fā)生此類問題時,根據(jù)原因的不同和應(yīng)用連接數(shù)據(jù)庫方式的不同,每秒的查詢數(shù)一般會下跌。所以我們可寫個腳本每秒去獲取數(shù)據(jù)庫的執(zhí)行狀態(tài),從而定位目前數(shù)據(jù)庫的負載能力。
- 使用 SHOW PROCESSLIST
通過 SHOW PROCESSLIST 找到數(shù)據(jù)庫下面,每個工作線程的執(zhí)行狀態(tài),如果某一業(yè)務(wù)下執(zhí)行比較慢,那么它的工作線程一定長時間處于查詢狀態(tài)(query),這時你就需要針對線程所在業(yè)務(wù)的 SQL 進行優(yōu)化。
- 「主要列含義」:
- id 列:一個標識,你要 kill 一個語句連接就有用它。
- user 列: 顯示當前用戶,如果不是 root,這個命令就只顯示你權(quán)限范圍內(nèi)的 sql 語句。
- command 列:顯示當前連接的執(zhí)行的命令,一般就是休眠(sleep),查詢(query),連接(connect),其他查詢鎖住(Locked)。
- state 列:顯示使用當前連接的 sql 語句的狀態(tài),很重要的列,請注意,state 只是語句執(zhí)行中的某一個狀態(tài),一個 sql 語句,以查詢?yōu)槔?#xff0c;可能需要經(jīng)過 copying to tmp table,Sorting result,Sending data 等狀態(tài)才可以完成。
- 使用慢日志查詢
如果要通過查詢?nèi)罩景l(fā)現(xiàn)問題,需要開啟慢查詢?nèi)罩静⒃谌旨墑e設(shè)置 「long_query_time 為 0」 , 還一個 log_output 參數(shù)要注意,它有 table 和 file 選擇,分別代表日志存儲為數(shù)據(jù)表還是文件。
并設(shè)置并且要確認所有的連接都采用了新的設(shè)置。這可能需要重置所有連接以使新的全局設(shè)置生效;
隨著服務(wù)器運行過久,日志文件可能達到幾百 G,這時候如果打開文件查找就不是一件理智的事情。可以根據(jù) MySQL 每秒將當前時間寫入日志中的模式統(tǒng)計每秒的查詢數(shù)量:
awk /^# Time:/{print $3, $4, c;c=0}/^# User/{c++}' slow-query.1og
如果發(fā)現(xiàn) mysql 吞吐量有高低起伏,直接根據(jù)對應(yīng)的時間點看到詳細的記錄,進而分析問題。
針對優(yōu)化之前,首先得看到 MySQL 的性能是否為服務(wù)資源不夠處理?什么業(yè)務(wù)線程執(zhí)行的慢?這個慢操作產(chǎn)生的原因是什么?等確定要優(yōu)化的問題。所以 show global status 和 show processlist 都是很好的手段。
減少掃描的行
要想減少掃描的行,就得看到有哪些途徑可以減 MySQL 查詢的行?「索引」 就是選擇
對索引原理不了解可以去看 互聯(lián)網(wǎng)大廠面試,談索引就直逼這些底層?難的是我不懂這些原理
當你查詢中用到了索引字段,那么一般都會使用到索引,這里列舉不會使用索引的方式,更重要的是明白索引的底層結(jié)構(gòu)是什么。
索引走不走還是得看字段在 where 條件后上的搭配與索引原理。因為多條件會涉及到「索引合并優(yōu)化」
注:索引合并優(yōu)化(Index merge optimization),當查詢中單張表可以使用多個索引時,同時掃描多個索引并將掃描結(jié)果進行合并。
- OR
使用它的前提條件,你需保證 OR 兩邊的字段都需要建立索引。如果不保證將退化為全表掃描。如:查詢
如果 c1 和 c2 列上分別有索引,可以按照 c1 和 c2 條件進行查詢,再將查詢結(jié)果合并(union)操作,得到最終結(jié)果。「使用了索引合并有什么特點?」
通過 explain 對 sql 語句進行分析,如果使用了索引合并,那么會在 type 列會顯示 index_merge,key 列會顯示出所有使用的索引。
為什么當 where 字段列,一旦其中有一個不是索引列。就不走索引掃描呢?
因為全表只掃一次,而你索引是根據(jù)字段的索引樹找的,索引最終就會合并全表和索引方式查找的的結(jié)果返回給客戶端。但掃描的方式就終確認為全表方式。
以下為匹配記錄:
如下是索引使用情況
很多人說 OR 需要用 union all 或者 in 優(yōu)化,如果都知道 OR 的索引觸發(fā)條件,還需進行結(jié)果搜索合并與 in 的條件限制嗎?你細品
- in
in 是查詢上面的一種組合方式,根據(jù)里面其字段值進行搜索,但如果這個組合條件過多就導致優(yōu)化器沒辦法很好的使用索引,并且使用 in 的字段需建立索引,這樣才能提升查找效率。
如:EXPLAIN SELECT * FROM users WHERE id in (5,8,9) AND name in ('Prof. Chase McKenzie II','Mr. Porter Prosacco IV') AND remember_token IN ('Wjz2H8WrpK', '5WYeM5FPKf');有索引:
無索引,直接全表掃描
EXPLAIN SELECT * FROM users WHERE name in ('Prof. Chase McKenzie II','Mr. Porter Prosacco IV') AND remember_token IN ('Wjz2H8WrpK', '5WYeM5FPKf');
- 范圍匹配
范圍條件的查詢,無法在使用范圍列后面的其他的索引列。一般可以優(yōu)化為多個等值查詢。即轉(zhuǎn)為 in 的過列字段進行值的匹配。
- != 和<>
如果索引字段使用到 != 和 <> 操作符,那么查詢引擎將放棄使用索引而進行全表掃描。因為優(yōu)化器會權(quán)衡查找的行數(shù),如果取反,那么剩下的數(shù)據(jù)查找的次數(shù)可能接近于全表,如果是二級索引還有回表的影響,更會加大 MySQL 的查找次數(shù)。
返回的行數(shù)
返回行數(shù)主要由不同類型的查詢,把數(shù)據(jù)從磁盤讀取到服務(wù)層后使用 where 后面的條件或者查詢相關(guān)語句來進行限制。
- count
使用 count 計數(shù)時,不要在括號里面指定一列來統(tǒng)計行數(shù),直接采用 count(*)性能會更好。這就有點難為人。為什么呢?
因為 MySQL 確認括號內(nèi)的表達式值不可能為空時,實際上就是在統(tǒng)計行數(shù)。當我們使用 COUNT()的時候,這種情況下通配符并不會像我們猜想的那樣擴展成所有的列,實際上,它會忽略所有的列而直接統(tǒng)計所有的行數(shù)。
都說:「MyISAM 的 COUNT()函數(shù)總是非常快,不過這是有前提條件的,即只有沒有任何 WHERE 條件的 COUNT(*) 才非常快」
因為此時無須實際地去計算表的行數(shù)。MySQL 可以利用存儲引擎的特性直接獲得這個值。如果 MySQL 知道某列 col 不可能為 NULL 值,那么 MySQL 內(nèi)部會將 COUNT(col)表達式優(yōu)化為 COUNT(*)。
那如何優(yōu)化?
- 反向操作
統(tǒng)計 ID 大于 5 的城市。可以像下面這樣來寫這個查詢:mysql> SELECT COUNT(*) FROM world.City WHERE ID > 5;
如果將條件反轉(zhuǎn)一下,先查找 ID 小于等于 5 的城市數(shù),然后用總城市數(shù)一一減就能得到同樣的結(jié)果,卻可以將掃描的行數(shù)減少到 5 行以內(nèi):
SELECT (SELECT COUNT(*) FROM world.City) - COUNT(*) FROM world.City WHERE ID <= 5;
- 關(guān)聯(lián)查詢
確保 ON 或者 USING 子句中的列上有索引。在創(chuàng)建索引的時候就要考慮到關(guān)聯(lián)的順序。當表 A 和表 B 用列 C 關(guān)聯(lián)的時候,如果優(yōu)化器的關(guān)聯(lián)順序是 B、A,那么就不需要在 B 表的對應(yīng)列上建索引。沒有用到的索引只會帶來額外的負擔。一般來說, 除非有其他理由,否則只需要在關(guān)聯(lián)順序中的第二個表的相應(yīng)列上創(chuàng)建索引。
確保任何的 GROUP BY 和 ORDER BY 中的表達式只涉及到一個表中的列,這樣 MySQL 才有可能使用索引來優(yōu)化這個過程。
- 子查詢關(guān)于子查詢優(yōu)化就是盡可能使用關(guān)聯(lián)查詢代替
- Group by 和 DISTINCT
MySQL 都使用同樣的辦法優(yōu)化這兩種查詢,事實上,MySQL 優(yōu)化器會在內(nèi)部處理的時候相互轉(zhuǎn)化這兩類查詢。它們都可以使用索引來優(yōu)化,這也是最有效的優(yōu)化辦法。在 MySQL 中,當無法使用索引的時候,GROUP BY 使用兩種策略來完成:使用臨時表或者文件排序來做分組
對于任何查詢語句,這兩種策略的性能都有可以提升的地方。可以通過使用提示 SQL_BIG_RESULT 和 SQL_SMALL_RESULT 來讓優(yōu)化器按照你希望的方式運行。
如果需要對關(guān)聯(lián)查詢做分組(GROUP BY),并且是按照查找表中的某個列進行分組,通常采用查找表的標識列分組的效率會比其它列更高。例如下面的查詢效率不會很好;
SELECT actor.first_name, actor.last_name, COUNT(*) FROM sakila.film_actor INNER JOIN sakila.actor USING(actor_id) GROUP BY actor.first_name, actor.last_name;
如果查詢按照下面的寫法效率則會更高:
SELECT actor.first name, actor.last name, COUNT(*) FROM sakila.film_actor INNER JOIN sakila.actor USING(actor.id) GROUP BY film_actor.actor.id;
使用 actor.actor_id 列分組的效率甚至會比使用 film_actor.actor_id 更好。如果沒有通過 ORDER BY 子句顯式地指定排序列,當查詢使用 GROUP BY 子句的時候,結(jié)果集會自動按照分組的字段進行排序。如果不關(guān)心結(jié)果集的順序,而這種默認排序又導致了需要文件排序,則可以使用 ORDER BY NULL, 讓 MySQL 不再進行文件排序。也可以在 GROUP BY 子句中直接使用 DESC 或者 ASC 關(guān)鍵字,使分組的結(jié)果集按需要的方向排序。
- Limit
在系統(tǒng)中需要進行分頁操作的時候,我們通常會使用 LIMIT 加上偏移量的辦法實現(xiàn),同時加上合適的 ORDER BY 子句。如果有對應(yīng)的索引,通常效率會不錯,否則,MySQL 需要做大量的文件排序操作。
一個非常令人頭疼的問題就是,在偏移量非常大的時候,例如可能是 LIMIT 10000,20 這樣的查詢,這時 MySQL 需要查詢 10020 條記錄然后只返回最后 20 條,前面 10000 條記錄都將被拋棄,這樣的代價非常高。如果所有的頁面被訪問的頻率都相同,那么這樣的查詢平均需要訪問半個表的數(shù)據(jù)。
要優(yōu)化這種查詢,要么是在頁面中限制分頁的數(shù)量,要么是優(yōu)化大偏移量的性能。優(yōu)化此類分頁查詢的個最簡單的辦法就是盡可能地使用索引覆蓋掃描,而不是查詢所有的列。然后根據(jù)需要做一次關(guān)聯(lián)操作再返回所需的列。對于偏移量很大的時候,這樣的效率會提升非常大。考慮下面的查詢:
SELECT f1lm_id, description FROM sakila.fi1m ORDER BY title LIMIT 50, 5;
如果表非常大,可改寫成這樣
SELECT film.film_id, film.description FROM sakila.film INNER JOIN ( SELECT film_id FROM sakila.film ORDER BY title LIMIT 50, 5 ) AS limt USING(film_id);
這里的“延遲關(guān)聯(lián)”將大大提升查詢效率,它讓 MySQL 掃描盡可能少的頁面,獲取需要訪問的記錄后再根據(jù)關(guān)聯(lián)列回原表查詢需要的所有列。這個技術(shù)也可以用于優(yōu)化關(guān)聯(lián)查詢中的 LIMIT 子句。
LIMIT 和 OFFSET 的問題,其實是 OFFSET 的問題,它會導致 MySQL 掃描大量不需要的行然后再拋棄掉。如果可以使用書簽記錄上次取數(shù)據(jù)的位置,那么下次就可以直接從該書簽記錄的位置開始掃描,這樣就可以避免使用 OFFSET。例如,若需要按照租借記錄做翻頁,那么可以根據(jù)最新一條租借記錄向后追溯,這種做法可行是因為租借記錄的主鍵是單調(diào)增長的。首先使用下面的查詢獲得第一組結(jié)果:
SELECT * FROM sakila.rental ORDER BY rental_id DESC LIMIT 20;
假設(shè)上面的查詢返回的是主鍵為 16049 到 16030 的租借記錄,那么下一頁查詢就可以從 16030 這個點開始:
SELECT * FROM sakila. rental WHERE rental id < 16030 ORDER BY rental id DESC LIMIT 20;
這樣無論翻頁到多么后面,其性能都會很好。還可以包括預(yù)先計算的匯總表,或者關(guān)聯(lián)到一個冗余表,冗余表只包含主鍵列和需要做排序的數(shù)據(jù)列。
設(shè)置最后一頁,分頁的時候,常用的技巧是在 LIMIT 語句中加上 SQL_CALC_FOUND_ROWS 提示,這樣就可以獲得去掉 LIMIT 以后滿足條件的行數(shù),因此可以作為分頁的總數(shù)。看起來,MySQL 做了一些非常“高深”的優(yōu)化,像是通過某種方法預(yù)測了總行數(shù)。但實際上,MySQL 只有在掃描了所有滿足條件的行以后,才會知道行數(shù),所以加上這個提示以后,不管是否需要,MySQL 都會掃描所有滿足條件的行,然后再拋棄掉不需要的行,而不是再滿足 LIMIT 的行數(shù)后就終止掃描。所以該提示的代價可能非常高。一個更好的設(shè)計是將具體的頁數(shù)換成“下一頁”按鈕,假設(shè)每頁顯示 20 條記錄,那么我們每次查詢時都是用 LIMIT 返回 21 條記錄并只顯示 20 條,如果第 21 條存在,那么我們就顯示“下一頁”按鈕,否則就說明沒有更多的數(shù)據(jù),也就無須顯示“下一頁”按鈕了。
另一種做法是先獲取并緩存較多的數(shù)據(jù),例如, 緩存 1000 條然后 每次分頁都從這個緩存中獲取。這樣做可以讓應(yīng)用程序根據(jù)結(jié)果集的大小采取不同的策略,如果結(jié)果集少于 1000,就可以在頁面上顯示所有的分頁鏈接,因為數(shù)據(jù)都在緩存中,所以這樣做性能不會有問題。如果結(jié)果集中于 1000,則可以在頁面上設(shè)計一個額外的“找到的結(jié)果多于 1000 條”之類的按鈕。這兩種策略都比每次生成全部結(jié)果集再拋棄掉不需要的數(shù)據(jù)的效率要高很多。
- UNION
MySQL 總是通過創(chuàng)建并填充臨時表的方式來執(zhí)行 UNION 查詢。因此很多優(yōu)化策略在 UNION 查詢中都沒法很好地使用。經(jīng)常需要手工地將 WHERE、LIMIT ORDERBY 等子句“下推”到 UNION 的各個子查詢中,以便優(yōu)化器可以充分利用這些條件進行優(yōu)化(例如,直接將這些子句冗余地寫一份到各個子查詢)。
總結(jié)
- SQL 優(yōu)化的重心由 3 方面消耗的時間來決定:響應(yīng)時間、掃描時間、查找時間。
- 掃描查詢主要由索引提速,如果一些其它條件(order by )與索引列相關(guān),那可保證掃描的數(shù)據(jù)行更少,這樣就不用在服務(wù)層做 where 處理。
- MySQL 優(yōu)化器會自行優(yōu)化 where 條件,讓執(zhí)行條件顯得更簡單。且編寫 where 條件也需考慮條件對結(jié)果數(shù)據(jù)的處理。
- 服務(wù)器負載也是很關(guān)鍵的,如果整體負載過高,那數(shù)據(jù)庫性能肯定會直線下降。
如有幫助,歡迎關(guān)注@蓮花童子哪吒
總結(jié)
以上是生活随笔為你收集整理的java的for循环取出数据只是拿到最后一个_一问SQL优化就无从藏身?那只是你对原理的精髓掌握不深的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python logging模块 默认_
- 下一篇: vc 通过句柄修改窗口大小_VC应用(1