這篇文章將為大家詳細(xì)講解有關(guān)如何在Postgres中處理海量數(shù)據(jù)以及使用分區(qū),文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
成都創(chuàng)新互聯(lián)成都網(wǎng)站建設(shè)按需定制制作,是成都網(wǎng)站制作公司,為成都陽臺(tái)護(hù)欄提供網(wǎng)站建設(shè)服務(wù),有成熟的網(wǎng)站定制合作流程,提供網(wǎng)站定制設(shè)計(jì)服務(wù):原型圖制作、網(wǎng)站創(chuàng)意設(shè)計(jì)、前端HTML5制作、后臺(tái)程序開發(fā)等。成都網(wǎng)站制作熱線:13518219792
我們發(fā)現(xiàn)個(gè)一個(gè)有趣的模式就是,在Postgres數(shù)據(jù)庫集群中會(huì)存在一、兩個(gè)表以較快的速度增長(zhǎng), 以量化的方式表示就是數(shù)GB或者數(shù)TB級(jí)別的大表。
通常情況下,這些表中存儲(chǔ)的數(shù)據(jù)通常是應(yīng)用程序中的事件跟蹤數(shù)據(jù),或者是應(yīng)用程序日志數(shù)據(jù)
這種規(guī)模的表在數(shù)據(jù)存儲(chǔ)上不是問題,但是存在其他方面的問題:
查詢性能的降低,更新索引變得緩慢。
維護(hù)時(shí)間變長(zhǎng),VACUUM(表空間整理)
你需要配置數(shù)據(jù)在應(yīng)用中的使用
在數(shù)據(jù)量隨著時(shí)間增長(zhǎng)時(shí), 通過使用Postgres表分區(qū)可以保證較高的查詢性能, 并且不需要將數(shù)據(jù)拆分保存在不同的數(shù)據(jù)存儲(chǔ)區(qū)域。
在我們的平臺(tái)中我們使用了pg_partman來維護(hù)表分區(qū), (廣告:)Heroku 平臺(tái)擁有Heroku Postgres,Heroku redis,Heroku Kafka 存儲(chǔ)編排服務(wù)
在我們的控制平臺(tái)中,我們擁有一個(gè)表, 表中存儲(chǔ)的數(shù)據(jù)是每個(gè)人的數(shù)據(jù)存儲(chǔ)的狀態(tài)變化記錄,在幾個(gè)星期以后,我們不需要使用這些信息,
這時(shí),我們使用表分區(qū)來完成這樣的動(dòng)作,在兩星期以后,我們就可以快速刪除這些表, 并且,在此期間其他查詢語句的速度不會(huì)受到影響。
要了解在大數(shù)據(jù)量的情況下,Postgre如何保證較高的性能, 我們需要Postgres 內(nèi)部是如何 如何使用繼承, 如何手動(dòng)設(shè)置表分區(qū), 學(xué)會(huì)使用 Postgres 擴(kuò)展模塊,pg_partman, 你可以學(xué)到更多Postgre分區(qū)設(shè)置和維護(hù)方法。
Postgres 具有對(duì)表分區(qū)通過表繼承的基本支持。 Postgres表繼承 和面向?qū)ο笾欣^承的概念一樣。 表據(jù)說是從另一個(gè)繼承,當(dāng)它保持相同的數(shù)據(jù)定義和接口。 Postgres 中實(shí)現(xiàn)表繼承已經(jīng)很長(zhǎng)時(shí)間了,這一功能也比較成熟,
看一下在我們的案例中一個(gè)表繼承是如何實(shí)現(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)品衍生出書籍和唱片, 這意味著如果一個(gè)記錄被插入到書表,它將有所有相同特性的產(chǎn)品表,再加上那書表。 如果對(duì)產(chǎn)品表發(fā)出的查詢,該查詢將參考產(chǎn)品表,再加上它的所有子信息。
對(duì)于此示例,該查詢將參考產(chǎn)品、書籍和唱片。
這是在 Postgres 的默認(rèn)行為。但是,您也可以發(fā)出對(duì)里面每個(gè)子表去做單獨(dú)的查詢
現(xiàn)在,我們有一個(gè)把握上繼承在 Postgres,我們將設(shè)置手動(dòng)分區(qū)。
分區(qū)的基本前提條件是主表存在從繼承的所有其他的孩子。
我們將使用短語子表和分區(qū)交替整個(gè)安裝過程的其余部分。
活數(shù)據(jù)不應(yīng)該存儲(chǔ)在主表上. 相反,當(dāng)數(shù)據(jù)往主表寫入的時(shí)候, 數(shù)據(jù)需要重定向到適當(dāng)?shù)淖臃謪^(qū)表中去, 此重定向操作通常是使用Postgres觸發(fā)器來實(shí)現(xiàn)的。 最重要的是,檢查約束放在每一個(gè)子表, 這樣,如果直接在子表中插入恰當(dāng)?shù)臄?shù)據(jù),則將插入成功。 如果數(shù)據(jù)不屬于分區(qū),那么就不會(huì)存入該分區(qū)表中去。
做表分區(qū),你需要選擇一個(gè)鍵來決定如何區(qū)分分區(qū)信息, 讓我們將我們的 Postgres 數(shù)據(jù)庫中一個(gè)非常大型的活動(dòng)表分區(qū)的過程。 對(duì)于一個(gè)事件表,時(shí)間是確定如何拆分出信息的關(guān)鍵。 讓我們假定,我們事件表獲取 1000 萬插入在任何給定的天完成, 下面是我們?cè)鹊氖录砑軜?gòu)︰
CREATE TABLE events ( uuid text, name text, user_id bigint, account_id bigint, created_at timestamptz );
讓我們做幾個(gè)更多的假設(shè)來證明該示例。 針對(duì)事件表運(yùn)行的聚合查詢僅有每一天的時(shí)間框架。 這意味著我們聚合分手小時(shí)為任何給定的一天。 我們使用事件表中的數(shù)據(jù)只有跨越了幾天。之后那個(gè)時(shí)候,我們不要再查詢數(shù)據(jù)。最重要的是, 我們有 1000 萬的事件生成的一天。
鑒于這些存在的假設(shè),我們有理由來創(chuàng)建日常分區(qū)。 我們使用表中數(shù)據(jù)的創(chuàng)建時(shí)間作為鍵值來對(duì)數(shù)據(jù)進(jìn)行分區(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);
我們的主表定義為事件表,有兩個(gè)子表用來存儲(chǔ)接受到的數(shù)據(jù), events_20160801 和 events_20160802。
我們也把它們以確保唯一數(shù)據(jù)的那一天結(jié)束在該分區(qū)上的 CHECK 約束。 現(xiàn)在我們需要?jiǎng)?chuàng)建一個(gè)觸發(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ā)器已添加到事件表。
在這一點(diǎn)上,我的應(yīng)用程序可以插入事件表上的數(shù)據(jù)和數(shù)據(jù)可以定向到適當(dāng)?shù)姆謪^(qū)。
那么問題來了,利用手工操作表分區(qū),會(huì)存在很多的失誤, 需要我們自己每次都去手動(dòng)更新分區(qū),創(chuàng)建觸發(fā)器,
我們還沒談?wù)摰缴形磸臄?shù)據(jù)庫中刪除舊數(shù)據(jù)。 這樣引入了pg_partman .
Postgres 使用 pg_partman,使使得表分區(qū)的管理更加簡(jiǎn)便(相較于手動(dòng)創(chuàng)建分區(qū)) 讓我們通過一個(gè)實(shí)例,這樣做從零開始運(yùn)行︰
首先,讓我們來加載擴(kuò)展和創(chuàng)建我們的事件表。 如果你已經(jīng)有一個(gè)大的表定義,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è),我們?cè)缧r(shí)候所作的事件數(shù)據(jù)。 我們每天產(chǎn)生1000萬的事件,我們的查詢聚合是以天為單位的。 鑒于此,我們要?jiǎng)?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>存在的另一個(gè)問題是</red>,這一創(chuàng)建分區(qū)的命令需要手動(dòng)執(zhí)行。
目前尚未實(shí)現(xiàn)數(shù)據(jù)庫的定期分區(qū)維護(hù),創(chuàng)建新的表分區(qū),轉(zhuǎn)移相關(guān)數(shù)據(jù)。
sushi::DATABASE=> SELECT run_maintenance();
run_maintenance() 命令將指示 pg_partman 仔細(xì)看看所有被分區(qū)的表, 并確定是否需要?jiǎng)?chuàng)建新的分區(qū)和摧毀舊分區(qū)。 無論應(yīng)銷毀一個(gè)分區(qū)或保留選項(xiàng)是否確定。 這個(gè)命令都將在終端命令行執(zhí)行。
我們需要設(shè)置定時(shí)任務(wù),使用Heroku調(diào)度程序來完成這項(xiàng)任務(wù),可以達(dá)到目的。 此命令將運(yùn)行每小時(shí)檢查一次數(shù)據(jù)庫表分區(qū),檢查分區(qū)和分區(qū)創(chuàng)建都在命令中,
Heroku 調(diào)度程序是一個(gè)很高效率的服務(wù), 每小時(shí)一次的執(zhí)行頻率并不會(huì)對(duì)數(shù)據(jù)庫產(chǎn)生明顯的性能影響.
就是這個(gè),我們已經(jīng)在Postgres中配置了表分區(qū),它將只是在后端做很少的維護(hù)動(dòng)作,
pg_partman的安裝過程(我們目前所做的)只是表象。
想要了解pg_partman 的更多細(xì)節(jié)的話,可以查看該拓展模塊的相關(guān)文檔.
###第四部分 重要的疑問:我需要使用表分區(qū)嗎?
表分區(qū)允許你打破了一個(gè)非常大的表成許多較小的表,來獲得較高的性能提升.
正如在 '手動(dòng)設(shè)置分區(qū)部分章節(jié)' 指出,許多挑戰(zhàn)存在時(shí)試圖創(chuàng)建并使用表分區(qū)自己
使用 pg_partman 可以減輕這種業(yè)務(wù)負(fù)擔(dān)。
盡管如此,表分區(qū)不是你解決一切問題的首選方案. 應(yīng)該問一些其他問題來確定使用表分區(qū)解決該是否合理︰
你有一個(gè)足夠大的數(shù)據(jù)集存儲(chǔ)在一個(gè)表中, 他隨著事件顯著增長(zhǎng)么?
數(shù)據(jù)是不可變的么?不可變是指,將它首次插入之后沒有更新操作么?
你在索引方面是否進(jìn)行過優(yōu)化?
經(jīng)過一段時(shí)間以后的數(shù)據(jù)還有價(jià)值么?
存在小范圍的數(shù)據(jù)查詢么?
可以將大規(guī)模的數(shù)據(jù)歸檔到一種廉價(jià)的存儲(chǔ)介質(zhì)上去么? 或者舊的數(shù)據(jù)需要做"聚合"或"匯總"計(jì)算么?
如果你對(duì)所有這些問題的回答是,你可以使用表分區(qū)。 總的來說,表分區(qū)需要你評(píng)估如何使用你的數(shù)據(jù), 從大架構(gòu)的設(shè)計(jì)角度使用和優(yōu)化去考慮它 表分區(qū)的使用需要你提前規(guī)劃,并考慮您的使用模式。 只要你考慮到了這些因素,使用表分區(qū)會(huì)對(duì)你的應(yīng)用性能提升帶來極大的幫助.
關(guān)于如何在Postgres中處理海量數(shù)據(jù)以及使用分區(qū)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
當(dāng)前文章:如何在Postgres中處理海量數(shù)據(jù)以及使用分區(qū)
網(wǎng)站路徑:http://chinadenli.net/article22/gshjjc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、移動(dòng)網(wǎng)站建設(shè)、自適應(yīng)網(wǎng)站、全網(wǎng)營(yíng)銷推廣、品牌網(wǎng)站建設(shè)、品牌網(wǎng)站制作
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)