您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關(guān)如何在Postgres中處理海量數(shù)據(jù)以及使用分區(qū),文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。
我們發(fā)現(xiàn)個一個有趣的模式就是,在Postgres數(shù)據(jù)庫集群中會存在一、兩個表以較快的速度增長, 以量化的方式表示就是數(shù)GB或者數(shù)TB級別的大表。
通常情況下,這些表中存儲的數(shù)據(jù)通常是應(yīng)用程序中的事件跟蹤數(shù)據(jù),或者是應(yīng)用程序日志數(shù)據(jù)
這種規(guī)模的表在數(shù)據(jù)存儲上不是問題,但是存在其他方面的問題:
查詢性能的降低,更新索引變得緩慢。
維護時間變長,VACUUM(表空間整理)
你需要配置數(shù)據(jù)在應(yīng)用中的使用
在數(shù)據(jù)量隨著時間增長時, 通過使用Postgres表分區(qū)可以保證較高的查詢性能, 并且不需要將數(shù)據(jù)拆分保存在不同的數(shù)據(jù)存儲區(qū)域。
在我們的平臺中我們使用了pg_partman來維護表分區(qū), (廣告:)Heroku 平臺擁有Heroku Postgres,Heroku Redis,Heroku Kafka 存儲編排服務(wù)
在我們的控制平臺中,我們擁有一個表, 表中存儲的數(shù)據(jù)是每個人的數(shù)據(jù)存儲的狀態(tài)變化記錄,在幾個星期以后,我們不需要使用這些信息,
這時,我們使用表分區(qū)來完成這樣的動作,在兩星期以后,我們就可以快速刪除這些表, 并且,在此期間其他查詢語句的速度不會受到影響。
要了解在大數(shù)據(jù)量的情況下,Postgre如何保證較高的性能, 我們需要Postgres 內(nèi)部是如何 如何使用繼承, 如何手動設(shè)置表分區(qū), 學(xué)會使用 Postgres 擴展模塊,pg_partman, 你可以學(xué)到更多Postgre分區(qū)設(shè)置和維護方法。
Postgres 具有對表分區(qū)通過表繼承的基本支持。 Postgres表繼承 和面向?qū)ο笾欣^承的概念一樣。 表據(jù)說是從另一個繼承,當(dāng)它保持相同的數(shù)據(jù)定義和接口。 Postgres 中實現(xiàn)表繼承已經(jīng)很長時間了,這一功能也比較成熟,
看一下在我們的案例中一個表繼承是如何實現(xiàn)的:
CREATE TABLE products ( id BIGSERIAL, price INTEGER created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ ); CREATE TABLE books ( isbn TEXT, author TEXT, title TEXT ) INHERITS (products); CREATE TABLE albums ( artist TEXT, length INTEGER, number_of_songs INTEGER ) INHERITS (products);
在此示例中,產(chǎn)品衍生出書籍和唱片, 這意味著如果一個記錄被插入到書表,它將有所有相同特性的產(chǎn)品表,再加上那書表。 如果對產(chǎn)品表發(fā)出的查詢,該查詢將參考產(chǎn)品表,再加上它的所有子信息。
對于此示例,該查詢將參考產(chǎn)品、書籍和唱片。
這是在 Postgres 的默認行為。但是,您也可以發(fā)出對里面每個子表去做單獨的查詢
現(xiàn)在,我們有一個把握上繼承在 Postgres,我們將設(shè)置手動分區(qū)。
分區(qū)的基本前提條件是主表存在從繼承的所有其他的孩子。
我們將使用短語子表和分區(qū)交替整個安裝過程的其余部分。
活數(shù)據(jù)不應(yīng)該存儲在主表上. 相反,當(dāng)數(shù)據(jù)往主表寫入的時候, 數(shù)據(jù)需要重定向到適當(dāng)?shù)淖臃謪^(qū)表中去, 此重定向操作通常是使用Postgres觸發(fā)器來實現(xiàn)的。 最重要的是,檢查約束放在每一個子表, 這樣,如果直接在子表中插入恰當(dāng)?shù)臄?shù)據(jù),則將插入成功。 如果數(shù)據(jù)不屬于分區(qū),那么就不會存入該分區(qū)表中去。
做表分區(qū),你需要選擇一個鍵來決定如何區(qū)分分區(qū)信息, 讓我們將我們的 Postgres 數(shù)據(jù)庫中一個非常大型的活動表分區(qū)的過程。 對于一個事件表,時間是確定如何拆分出信息的關(guān)鍵。 讓我們假定,我們事件表獲取 1000 萬插入在任何給定的天完成, 下面是我們原先的事件表架構(gòu)︰
CREATE TABLE events ( uuid text, name text, user_id bigint, account_id bigint, created_at timestamptz );
讓我們做幾個更多的假設(shè)來證明該示例。 針對事件表運行的聚合查詢僅有每一天的時間框架。 這意味著我們聚合分手小時為任何給定的一天。 我們使用事件表中的數(shù)據(jù)只有跨越了幾天。之后那個時候,我們不要再查詢數(shù)據(jù)。最重要的是, 我們有 1000 萬的事件生成的一天。
鑒于這些存在的假設(shè),我們有理由來創(chuàng)建日常分區(qū)。 我們使用表中數(shù)據(jù)的創(chuàng)建時間作為鍵值來對數(shù)據(jù)進行分區(qū)(例如 created_at)
CREATE TABLE events ( uuid text, name text, user_id bigint, account_id bigint, created_at timestamptz ); CREATE TABLE events_20160801 ( CHECK (created_at >= '2016-08-01 00:00:00' AND created_at < '2016-08-02 00:00:00') ) INHERITS (events); CREATE TABLE events_20160802 ( CHECK (created_at >= '2016-08-02 00:00:00' AND created_at < '2016-08-03 00:00:00') ) INHERITS (events);
我們的主表定義為事件表,有兩個子表用來存儲接受到的數(shù)據(jù), events_20160801 和 events_20160802。
我們也把它們以確保唯一數(shù)據(jù)的那一天結(jié)束在該分區(qū)上的 CHECK 約束。 現(xiàn)在我們需要創(chuàng)建一個觸發(fā)器,以確保在主表中輸入任何數(shù)據(jù)都能夠去尋找正確的分區(qū)︰
CREATE OR REPLACE FUNCTION event_insert_trigger() RETURNS TRIGGER AS $$ BEGIN IF ( NEW.created_at >= '2016-08-01 00:00:00'AND NEW.created_at < '2016-08-02 00:00:00' ) THEN INSERT INTO events_20160801 VALUES (NEW.*); ELSIF ( NEW.created_at >= '2016-08-02 00:00:00'AND NEW.created_at < '2016-08-03 00:00:00' ) THEN INSERT INTO events_20160802 VALUES (NEW.*); ELSE RAISE EXCEPTION 'Date out of range. Fix the event_insert_trigger() function!'; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql; CREATE TRIGGER insert_event_trigger BEFORE INSERT ON event FOR EACH ROW EXECUTE PROCEDURE event_insert_trigger();
太好了 !分區(qū)創(chuàng)建,觸發(fā)功能定義,并且觸發(fā)器已添加到事件表。
在這一點上,我的應(yīng)用程序可以插入事件表上的數(shù)據(jù)和數(shù)據(jù)可以定向到適當(dāng)?shù)姆謪^(qū)。
那么問題來了,利用手工操作表分區(qū),會存在很多的失誤, 需要我們自己每次都去手動更新分區(qū),創(chuàng)建觸發(fā)器,
我們還沒談?wù)摰缴形磸臄?shù)據(jù)庫中刪除舊數(shù)據(jù)。 這樣引入了pg_partman .
Postgres 使用 pg_partman,使使得表分區(qū)的管理更加簡便(相較于手動創(chuàng)建分區(qū)) 讓我們通過一個實例,這樣做從零開始運行︰
首先,讓我們來加載擴展和創(chuàng)建我們的事件表。 如果你已經(jīng)有一個大的表定義,pg_partman 文件具有指導(dǎo)意義,如何將該表格轉(zhuǎn)換成一種使用表分區(qū)。
$ heroku pg:psql -a sushi sushi::DATABASE=> CREATE EXTENSION pg_partman; sushi::DATABASE=> CREATE TABLE events ( id bigint, name text, properities jsonb, created_at timestamptz );
繼續(xù)使用我們的假設(shè),我們早些時候所作的事件數(shù)據(jù)。 我們每天產(chǎn)生1000萬的事件,我們的查詢聚合是以天為單位的。 鑒于此,我們要創(chuàng)建按天來創(chuàng)建分區(qū)。
sushi::DATABASE=> SELECT create_parent('public.events', 'created\_at', 'time', 'daily');
此命令告訴 pg_partman,使用數(shù)據(jù)表的create_at列作為鍵來創(chuàng)建分區(qū),
到這里<red>存在的另一個問題是</red>,這一創(chuàng)建分區(qū)的命令需要手動執(zhí)行。
目前尚未實現(xiàn)數(shù)據(jù)庫的定期分區(qū)維護,創(chuàng)建新的表分區(qū),轉(zhuǎn)移相關(guān)數(shù)據(jù)。
sushi::DATABASE=> SELECT run_maintenance();
run_maintenance() 命令將指示 pg_partman 仔細看看所有被分區(qū)的表, 并確定是否需要創(chuàng)建新的分區(qū)和摧毀舊分區(qū)。 無論應(yīng)銷毀一個分區(qū)或保留選項是否確定。 這個命令都將在終端命令行執(zhí)行。
我們需要設(shè)置定時任務(wù),使用Heroku調(diào)度程序來完成這項任務(wù),可以達到目的。 此命令將運行每小時檢查一次數(shù)據(jù)庫表分區(qū),檢查分區(qū)和分區(qū)創(chuàng)建都在命令中,
Heroku 調(diào)度程序是一個很高效率的服務(wù), 每小時一次的執(zhí)行頻率并不會對數(shù)據(jù)庫產(chǎn)生明顯的性能影響.
就是這個,我們已經(jīng)在Postgres中配置了表分區(qū),它將只是在后端做很少的維護動作,
pg_partman的安裝過程(我們目前所做的)只是表象。
想要了解pg_partman 的更多細節(jié)的話,可以查看該拓展模塊的相關(guān)文檔.
###第四部分 重要的疑問:我需要使用表分區(qū)嗎?
表分區(qū)允許你打破了一個非常大的表成許多較小的表,來獲得較高的性能提升.
正如在 '手動設(shè)置分區(qū)部分章節(jié)' 指出,許多挑戰(zhàn)存在時試圖創(chuàng)建并使用表分區(qū)自己
使用 pg_partman 可以減輕這種業(yè)務(wù)負擔(dān)。
盡管如此,表分區(qū)不是你解決一切問題的首選方案. 應(yīng)該問一些其他問題來確定使用表分區(qū)解決該是否合理︰
你有一個足夠大的數(shù)據(jù)集存儲在一個表中, 他隨著事件顯著增長么?
數(shù)據(jù)是不可變的么?不可變是指,將它首次插入之后沒有更新操作么?
你在索引方面是否進行過優(yōu)化?
經(jīng)過一段時間以后的數(shù)據(jù)還有價值么?
存在小范圍的數(shù)據(jù)查詢么?
可以將大規(guī)模的數(shù)據(jù)歸檔到一種廉價的存儲介質(zhì)上去么? 或者舊的數(shù)據(jù)需要做"聚合"或"匯總"計算么?
如果你對所有這些問題的回答是,你可以使用表分區(qū)。 總的來說,表分區(qū)需要你評估如何使用你的數(shù)據(jù), 從大架構(gòu)的設(shè)計角度使用和優(yōu)化去考慮它 表分區(qū)的使用需要你提前規(guī)劃,并考慮您的使用模式。 只要你考慮到了這些因素,使用表分區(qū)會對你的應(yīng)用性能提升帶來極大的幫助.
關(guān)于如何在Postgres中處理海量數(shù)據(jù)以及使用分區(qū)就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。