日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

Postgresql刪除數據庫表中重復數據的幾種方法詳解_PostgreSQL

作者:波多爾斯基 ? 更新時間: 2022-11-20 編程語言

一直使用Postgresql數據庫,有一張表是這樣的:

DROP TABLE IF EXISTS "public"."devicedata";
CREATE TABLE "public"."devicedata" (
  "Id" varchar(200) COLLATE "pg_catalog"."default" NOT NULL,
  "DeviceId" varchar(200) COLLATE "pg_catalog"."default",
  "Timestamp" int8,
  "DataArray" float4[]
)

CREATE INDEX "timeIndex" ON "public"."devicedata" USING btree (
  "Timestamp" "pg_catalog"."int8_ops" DESC NULLS LAST,
  "DeviceId" COLLATE "pg_catalog"."default" "pg_catalog"."text_ops" ASC NULLS LAST
);

ALTER TABLE "public"."devicedata" ADD CONSTRAINT "devicedata_pkey" PRIMARY KEY ("Id");

主鍵為Id,是通過程序生成的GUID,隨著數據表的越來越大(70w),即便我建立了索引,查詢效率依然不樂觀。

使用GUID作為數據庫的主鍵對分布式應用比較友好,但是不利于數據的插入,可以使用類似ABP的方法生成連續的GUID解決這個問題。

為了進行優化,計劃使用DeviceId與Timestamp作為主鍵,由于主鍵會自動建立索引,使用這兩個字段查詢的時候,查詢效率可以有很大的提升。不過,由于數據庫的插入了很多的重復數據,直接切換主鍵不可行,需要先剔除重復數據。

使用group by

數據量小的時候適用。對于我這個70w的數據,查詢運行了半個多小時也無法完成。

DELETE FROM "DeviceData"
WHERE "Id"
NOT IN (
SELECT max("Id")
FROM "DeviceData_temp"
GROUP BY "DeviceId", "Timestamp"
);

使用DISTINCT

建立一張新表然后插入數據,或者使用select into語句。

SELECT DISTINCT "Timestamp", "DeviceId"
INTO "DeviceData_temp"
FROM "DeviceData";
-- 刪除原表
DROP TABLE "DeviceData";
-- 將新表重命名
ALTER TABLE "DeviceData_temp" RENAME TO "DeviceData";

不過這個問題也非常大,很明顯,未來的表,是不需要Id列的,但是DataArray也沒有了,沒有意義。

如果SELECT DISTINCT "Timestamp", "DeviceId", "DataArray",那么可能出現"Timestamp", "DeviceId"重復的現象。

使用ON CONFLICT

如果我們直接建立新表格,設置好新的主鍵,然后插入數據,如果重復了就跳過不就行了?但是使用select into是不行了,重復的數據會導致語句執行中斷。需要借助upsert(on conflict)方法。

INSERT INTO "DeviceData_temp"
SELECT * FROM "DeviceData"
on conflict("DeviceId", "Timestamp") DO NOTHING;
-- 刪除原表
DROP TABLE "DeviceData";
-- 將新表重命名
ALTER TABLE "DeviceData_temp" RENAME TO "DeviceData";

執行不到100s就完成了,刪除了許多重復數據。

原文鏈接:https://www.cnblogs.com/podolski/p/16745080.html

欄目分類
最近更新