delete后加 limit是個好習(xí)慣么 !
超全面!Java核心知識總結(jié)
超全面!Java核心知識總結(jié)
作者:_陳哈哈
https://blog.csdn.net/qq_39390545/article/details/107519747
那么,在日常執(zhí)行 delete 時,我們是否需要養(yǎng)成加 limit 的習(xí)慣呢?是不是一個好習(xí)慣呢?
在日常的 SQL 編寫中,你寫 delete 語句時是否用到過以下 SQL?
delete from t where sex = 1 limit 100;?
你或許沒有用過,在一般場景下,我們對 delete 后是否需要加 limit 的問題很陌生,也不知有多大區(qū)別,今天帶你來了解一下,記得 mark!
寫在前面,如果是清空表數(shù)據(jù)建議直接用 truncate,效率上 truncate 遠(yuǎn)高于 delete,應(yīng)為 truncate 不走事務(wù),不會鎖表,也不會生產(chǎn)大量日志寫入日志文件;truncate table table_name 后立刻釋放磁盤空間,并重置 auto_increment 的值。delete 刪除不釋放磁盤空間,但后續(xù) insert 會覆蓋在之前刪除的數(shù)據(jù)上。詳細(xì)了解請?zhí)D(zhuǎn)另一篇博文《delete、truncate、drop 的區(qū)別有哪些,該如何選擇》
下面只討論 delete 場景,首先,delete 后面是支持 limit 關(guān)鍵字的,但僅支持單個參數(shù),也就是 [limit row_count],用于告知服務(wù)器在控制命令被返回到客戶端前被刪除的行的最大值。
delete limit 語法如下,值得注意的是,order by 必須要和 limit 聯(lián)用,否則就會被優(yōu)化掉。
delete \[low\_priority\] \[quick\] \[ignore\] from tbl\_name
\[where ...\]
\[order by ...\]
\[limit row\_count\]
加 limit 的的優(yōu)點(diǎn):
以下面的這條 SQL 為例:
delete from t where sex = 1;?
1. 降低寫錯 SQL 的代價,就算刪錯了,比如 limit 500, 那也就丟了 500 條數(shù)據(jù),并不致命,通過 binlog 也可以很快恢復(fù)數(shù)據(jù)。
2. 避免了長事務(wù),delete 執(zhí)行時 MySQL 會將所有涉及的行加寫鎖和 Gap 鎖(間隙鎖),所有 DML 語句執(zhí)行相關(guān)行會被鎖住,如果刪除數(shù)量大,會直接影響相關(guān)業(yè)務(wù)無法使用。
3. delete 數(shù)據(jù)量大時,不加 limit 容易把 cpu 打滿,導(dǎo)致越刪越慢。
針對上述第二點(diǎn),前提是 sex 上加了索引,大家都知道,加鎖都是基于索引的,如果 sex 字段沒索引,就會掃描到主鍵索引上,那么就算 sex = 1 的只有一條記錄,也會鎖表。
對于 delete limit 的使用,MySQL 大佬丁奇有一道題:
如果你要刪除一個表里面的前 10000 行數(shù)據(jù),有以下三種方法可以做到:
第一種,直接執(zhí)行 delete from T limit 10000;
第二種,在一個連接中循環(huán)執(zhí)行 20 次 delete from T limit 500;
第三種,在 20 個連接中同時執(zhí)行 delete from T limit 500。
你先考慮一下,再看看幾位老鐵的回答:
--------------------------------------------
Tony Du:
方案一,事務(wù)相對較長,則占用鎖的時間較長,會導(dǎo)致其他客戶端等待資源時間較長。
方案二,串行化執(zhí)行,將相對長的事務(wù)分成多次相對短的事務(wù),則每次事務(wù)占用鎖的時間相對較短,其他客戶端在等待相應(yīng)資源的時間也較短。這樣的操作,同時也意味著將資源分片使用(每次執(zhí)行使用不同片段的資源),可以提高并發(fā)性。
方案三,人為自己制造鎖競爭,加劇并發(fā)量。
方案二相對比較好,具體還要結(jié)合實(shí)際業(yè)務(wù)場景。
--------------------------------------------
肉山:
不考慮數(shù)據(jù)表的訪問并發(fā)量,單純從這個三個方案來對比的話。
第一個方案,一次占用的鎖時間較長,可能會導(dǎo)致其他客戶端一直在等待資源。
第二個方案,分成多次占用鎖,串行執(zhí)行,不占有鎖的間隙其他客戶端可以工作,類似于現(xiàn)在多任務(wù)操作系統(tǒng)的時間分片調(diào)度,大家分片使用資源,不直接影響使用。
第三個方案,自己制造了鎖競爭,加劇并發(fā)。
至于選哪一種方案要結(jié)合實(shí)際場景,綜合考慮各個因素吧,比如表的大小,并發(fā)量,業(yè)務(wù)對此表的依賴程度等。
-------------------------------------------
~嗡嗡:
1. 直接 delete 10000 可能使得執(zhí)行事務(wù)時間過長
2. 效率慢點(diǎn)每次循環(huán)都是新的短事務(wù),并且不會鎖同一條記錄,重復(fù)執(zhí)行 DELETE 知道影響行為 0 即可
3. 效率雖高,但容易鎖住同一條記錄,發(fā)生死鎖的可能性比較高
-------------------------------------------
第一種方式(即:直接執(zhí)行 delete from T limit 10000)里面,單個語句占用時間長,鎖的時間也比較長;而且大事務(wù)還會導(dǎo)致主從延遲。
第三種方式(即:在 20 個連接中同時執(zhí)行 delete from T limit 500),會人為造成鎖沖突。
好了,本文就帶你了解這些,如果有相關(guān)疑問和好想法,請在下方留言,方便和小伙伴兒們一起討論。
如有文章對你有幫助,
“在看”和轉(zhuǎn)發(fā)是對我最大的支持!
最后,分享一份?Java核心知識手冊? 包含了JVM、Java集合、Java多線程并發(fā)、Java基礎(chǔ)、Spring原理、微服務(wù)、Netty和RPC、網(wǎng)絡(luò)、日志、Zookeeper、KafKa、RabbitMQ、Hbase、MongoDB、Cassandra、設(shè)計模式、負(fù)載均衡、數(shù)據(jù)庫、一致性算法、Java算法、數(shù)據(jù)結(jié)構(gòu)、加密算法、分布式緩存、Hadoop、Spark、Storm...
點(diǎn)擊下方圖片,即可獲取


