柚子快報激活碼778899分享:MySQL三種去重方式比較
柚子快報激活碼778899分享:MySQL三種去重方式比較
引言:
在MySQL數(shù)據(jù)庫中,數(shù)據(jù)去重是一項常見的操作。通過去除重復(fù)的數(shù)據(jù),可以提高查詢效率和數(shù)據(jù)的整潔度。本文將比較MySQL中常用的三種去重方式,包括使用DISTINCT關(guān)鍵字、使用GROUP BY子句和使用窗口函數(shù)ROW_NUMBER(),以幫助讀者選擇最適合自己的去重方法。
三種去重方法介紹:
使用DISTINCT關(guān)鍵字: DISTINCT關(guān)鍵字是MySQL提供的一種去重方式。它可以用在SELECT語句中,去除查詢結(jié)果中的重復(fù)記錄。使用DISTINCT關(guān)鍵字的語法簡單,只需要在SELECT關(guān)鍵字之后加上DISTINCT即可,這種方式適用于對單個列或多個列進行去重的情況。 SELECT DISTINCT column1, column2 FROM table_name
優(yōu)點: 1.語法簡單明了,容易理解和使用。
2.可以同時對多個列進行去重,靈活性較好。
缺點: 1.DISTINCT關(guān)鍵字只能按照select的列進行去重,如果需要查詢其他不用去重的列,需要額外處理。
使用GROUP BY子句: GROUP BY子句是另一種常用的去重方式。它將查詢結(jié)果按照指定的列進行分組,并對每個分組進行聚合操作。通過使用GROUP BY子句,我們可以將重復(fù)的記錄分組合并,達到去重的效果。
優(yōu)點: 1.可以對多個列進行分組和進行組內(nèi)聚合操作,提供更靈活的功能。
缺點: 1.GROUP BY子句的語法比較復(fù)雜,學(xué)習(xí)和理解成本較高。
2.如果需要返回不在group by里面的字段,需要設(shè)置sql_model參數(shù)。
3.需要注意使用聚合函數(shù)處理分組后的數(shù)據(jù)。
使用窗口函數(shù)ROW_NUMBER(): ROW_NUMBER()函數(shù)是SQL中的一個窗口函數(shù),用于為每一行數(shù)據(jù)分配一個唯一的序列號,當(dāng)根據(jù)需要的字段排序后,取序列號為1的數(shù)據(jù),即可完成去重操作。 -- example
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY column1, column2, ... ORDER BY column1, column2, ...) AS rn
FROM table
) AS subquery
WHERE rn = 1;
優(yōu)點: 1.ROW_NUMBER()函數(shù)是SQL標(biāo)準(zhǔn)中提供的窗口函數(shù)之一,使用廣泛且簡單易懂。
2.可以根據(jù)需要按照分組后的結(jié)果的某列或者某幾列再進行組內(nèi)分組排序,然后通過將ROW_NUMBER()結(jié)果為1的行保留下來,可以實現(xiàn)對重復(fù)數(shù)據(jù)的去重操作。
3.通過在ORDER BY子句中指定不同的列和排序順序,可以靈活地根據(jù)具體需求進行去重和排序。
缺點: 1.只能去重連續(xù)行:ROW_NUMBER()函數(shù)只能對連續(xù)的行(分組后的組內(nèi))進行排序和排除,如果要處理非連續(xù)(分組后的非組內(nèi))的重復(fù)行,需要采用其他的方法。
3.語法復(fù)雜:語法中涉及到嵌套查詢和窗口函數(shù)的使用,相對于其他簡單的去重方法,可能稍顯復(fù)雜一些。
效率比較:
首先建立一個測試表,制造一些簡單的測試數(shù)據(jù),數(shù)據(jù)量大概在200w+,如果數(shù)據(jù)量少很難觀察到效果:
-- test.out_order_item definition
CREATE TABLE `out_order_item` (
`id` int NOT NULL AUTO_INCREMENT,
`sale_order_id` int NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
);
沒有索引的情況: -- group by方式
select
sale_order_id
from
test.out_order_item
group by
sale_order_id
limit 200;
-- 運行10次,2.5s左右
-- limit數(shù)量不受影響
-- distinct方式
select
distinct sale_order_id
from
test.out_order_item
limit 200;
-- 運行10次,5ms左右
-- limit 20000, 40ms左右
-- limit 2000000, 2.5s左右
-- row_number方式
select
sale_order_id
from
(select
row_number() over(partition by sale_order_id) rn,
sale_order_id
from test.out_order_item) a
where
rn = 1
limit 200;
-- 運行10次,5.5s左右
-- limit數(shù)量不受影響
有索引的情況: 先給表字段sale_order_id添加索引 CREATE INDEX sale_order_id_IDX USING BTREE ON test.out_order_item (sale_order_id);
-- group by方式
select
sale_order_id
from
test.out_order_item
group by
sale_order_id
limit 200;
-- 運行10次,1ms左右
-- limit 20000,40ms左右
-- limit 2000000,1.2s左右
-- distinct方式
select
distinct sale_order_id
from
test.out_order_item
limit 200;
-- 運行10次,1ms左右
-- limit 20000, 40ms左右
-- limit 2000000, 1.5s左右
-- row_number方式
select
sale_order_id
from
(select
row_number() over(partition by sale_order_id) rn,
sale_order_id
from test.out_order_item) a
where
rn = 1
limit 200;
-- 運行10次,5.5s左右
-- limit數(shù)量不受影響
結(jié)論:
從上面的結(jié)果的執(zhí)行時間可以看出,三種去重方法可以適用于不同的場景,而且其效率也不相同。
適用場景:
distinct:簡單的字段去重,不需要其他操作;group by:需要進行額外的聚合處理;row_number():想要返回非去重的其他列; 效率影響:
無索引情況
distinct:取決于返回結(jié)果集的大小,數(shù)量遠(yuǎn)小于表數(shù)量時性能最好;group by:不受結(jié)果集影響,性能中等;row_number():不受結(jié)果集影響,性能最差; 有索引情況
distinct:取決于返回結(jié)果集的大小,結(jié)果集少時與group by相差不大;group by:取決于返回結(jié)果集的大小,結(jié)果集大時,比distinct性能好;row_number():不受結(jié)果集影響,性能最差;
以上是簡單的從現(xiàn)象得出的結(jié)論,有興趣研究其原因的小伙伴可以通過explain關(guān)鍵字看看執(zhí)行計劃,分析為何出現(xiàn)這種情況,這里就先不展開具體分析。
柚子快報激活碼778899分享:MySQL三種去重方式比較
好文閱讀
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。