欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

PostgreSQL表膨脹問題解析及解決方案

 更新時間:2024年11月25日 09:36:01   作者:拾光編程  
表膨脹是指表的數(shù)據(jù)和索引所占文件系統(tǒng)的空間在有效數(shù)據(jù)量并未發(fā)生大的變化的情況下不斷增大,這種現(xiàn)象會導致關(guān)系文件被大量空洞填滿,從而浪費大量的磁盤空間,本文給大家介紹了PostgreSQL表膨脹問題解析及解決方案,需要的朋友可以參考下

一、定義

表膨脹是指表的數(shù)據(jù)和索引所占文件系統(tǒng)的空間在有效數(shù)據(jù)量并未發(fā)生大的變化的情況下不斷增大。這種現(xiàn)象會導致關(guān)系文件被大量空洞填滿,從而浪費大量的磁盤空間。

二、原因

表膨脹在PostgreSQL中通常是由于UNDO數(shù)據(jù)(用于回滾事務和維護事務的一致性視圖)和表數(shù)據(jù)混合存儲引起的。具體原因包括以下幾個方面:

1. MVCC(多版本并發(fā)控制)機制:

  • 舊版本數(shù)據(jù)保留:PostgreSQL使用MVCC機制來處理并發(fā)訪問,允許讀取操作在不鎖定表的情況下進行。當一條記錄被更新或刪除時,原始記錄不會立即從磁盤上移除,而是被標記為不可見,以支持未提交的事務回滾或者用于快照讀。這些舊版本的數(shù)據(jù)如果不能得到及時清理,就會占用磁盤空間,導致表膨脹。
  • 死元組(dead tuple):隨著時間的推移,表中會積累大量的“死”行(即不再可達的行),這些死元組如果不及時清理,就會占用磁盤空間。

2. 頻繁的更新和刪除操作:

  • 死元組積累:頻繁的更新和刪除操作直接導致表中大量的“死”行。在高更新和刪除率的環(huán)境中,表膨脹尤為嚴重,因為每次這些操作發(fā)生時,都會留下不再可達的行。

3. 未提交的事務:

  • 資源占用:長時間未提交或終止的事務會占用資源,導致“死”行的積累,進而導致表膨脹。

4. 填充因子(fillfactor)設(shè)置:

  • 空閑空間:表的填充因子設(shè)置也會影響表膨脹。較低的填充因子意味著每個數(shù)據(jù)頁中會留出更多的空閑空間,以減少頁面因更新而頻繁分裂的可能性。但這會增加每個頁面的空閑空間,導致表的實際磁盤使用量增加。相反,較高的填充因子可能導致數(shù)據(jù)行更新時空間不足,需要重新分配頁面。

5. autovacuum機制不足:

  • 清理不及時:雖然PostgreSQL提供了自動的autovacuum機制來定期清理“死”行,但在某些情況下,如高并發(fā)事務、長事務等,autovacuum可能無法及時清理死元組,導致表膨脹。

6. 其他因素:

  • 失效復制槽:失效的復制槽可能導致autovacuum無法正常工作。
  • 索引狀態(tài)問題:表和索引的并發(fā)訪問可能影響VACUUM的效果。
  • 磁盤I/O性能:磁盤I/O性能差可能導致VACUUM的效率低下,死元組不能及時清理。

三、影響

表膨脹對數(shù)據(jù)庫的性能和穩(wěn)定性有顯著影響,具體包括以下幾個方面:

1. 存儲成本增加:

膨脹的表占用更多磁盤空間,增加存儲成本。

2. 查詢性能下降:

  • 數(shù)據(jù)集增大:數(shù)據(jù)庫需要在更大的數(shù)據(jù)集中搜索,導致查詢執(zhí)行時間延長。
  • 索引效率降低:表膨脹可能導致索引結(jié)構(gòu)效率下降。

3. 備份恢復時間延長:

表變大后相應的備份恢復時間也會延長。

4. 系統(tǒng)資源消耗增加:

  • CPU、內(nèi)存和I/O資源:處理膨脹的表需要更多的CPU、內(nèi)存和I/O資源。

5. 數(shù)據(jù)碎片化:

表膨脹可能導致數(shù)據(jù)碎片化,進一步影響性能并增加數(shù)據(jù)庫管理的復雜性。

四、解決方案

解決表膨脹問題通常涉及到以下幾個步驟:

1. 定期執(zhí)行VACUUM操作:

  • 普通VACUUM:清理死元組,但不會進行空間重組,磁盤上的空間不會釋放,但后續(xù)的插入會根據(jù)空閑空間管理優(yōu)先插入空閑空間。
  • VACUUM FULL:清理釋放磁盤空間,但獲取的鎖級別較高,會阻塞一切訪問,適用于經(jīng)常進行大批量更新數(shù)據(jù)的表,可以在業(yè)務低峰期執(zhí)行。
  • 手動VACUUM:通過調(diào)整VACUUM的行為(如VACUUM(FULL, FREEZE)),可以更快地清理UNDO數(shù)據(jù)。

2. 啟用和配置autovacuum機制:

  • 確保autovacuum開啟:PostgreSQL提供了自動的autovacuum機制,可以根據(jù)閾值自動觸發(fā)vacuum操作。
  • 調(diào)整autovacuum參數(shù):如autovacuum_vacuum_cost_delay和autovacuum_naptime,以確保autovacuum進程能夠及時清理“死”行。
  • 監(jiān)控autovacuum效果:定期檢查autovacuum的執(zhí)行情況和效果,確保其正常工作。

3. 使用pg_repack或pg_reorg工具:

  • 在線重組:對于膨脹嚴重的表,可以使用pg_repack或pg_reorg等工具重新組織表和索引以回收空間。這些工具可以在不鎖定表的情況下工作,對生產(chǎn)環(huán)境影響較小。
  • 執(zhí)行過程
    • 準備階段:預留足夠的磁盤空間,調(diào)整數(shù)據(jù)庫參數(shù)(如idle_in_transaction_session_timeout)。
    • 執(zhí)行階段:創(chuàng)建新表,復制數(shù)據(jù),建立索引,交換表等。
    • 監(jiān)控和日志:監(jiān)控重組過程,記錄日志以便問題排查。

4. 合理設(shè)計數(shù)據(jù)庫和查詢:

  • 避免頻繁的更新和刪除操作:減少“死”行的積累。
  • 使用分區(qū)表:對于頻繁更新的大表,可以考慮分區(qū)表以減少單個表的大小和膨脹程度。
  • 合理設(shè)置填充因子:根據(jù)表的更新頻率和數(shù)據(jù)量合理設(shè)置填充因子以減少表膨脹的可能性。

5. 監(jiān)控和預警:

  • 建立監(jiān)控體系:對表的膨脹情況進行實時監(jiān)測并設(shè)置閾值告警,一旦發(fā)現(xiàn)表膨脹現(xiàn)象能快速響應處理。
  • 定期分析:定期分析表的膨脹情況和原因,采取相應的優(yōu)化措施。

6. 其他優(yōu)化措施:

  • 配置REDO日志:如果可能,可以配置REDO日志使得UNDO數(shù)據(jù)和REDO日志分離以減少表膨脹的影響。
  • 數(shù)據(jù)庫維護最佳實踐:定期的數(shù)據(jù)庫維護活動如索引優(yōu)化、統(tǒng)計信息更新等也有助于管理UNDO數(shù)據(jù)。

五、實施說明

1. 啟用和配置autovacuum機制:

確保autovacuum開啟

ALTER SYSTEM SET autovacuum = on;
SELECT pg_reload_conf();

調(diào)整autovacuum參數(shù):

ALTER SYSTEM SET autovacuum_vacuum_cost_delay = 20ms;
ALTER SYSTEM SET autovacuum_naptime = 1min;
SELECT pg_reload_conf();

監(jiān)控autovacuum效果

SELECT * FROM pg_stat_autovacuum;

2. 定期執(zhí)行VACUUM操作:

手動執(zhí)行VACUUM

VACUUM FULL tablename;

設(shè)置定時任務

0 2 * * * psql -d yourdatabase -c "VACUUM FULL tablename"

3. 使用pg_repack工具:

安裝pg_repack擴展

CREATE EXTENSION pg_repack;

執(zhí)行pg_repack

pg_repack -h your_host -p your_port -d your_database -t your_table

監(jiān)控重組過程

SELECT * FROM pg_stat_activity WHERE query LIKE '%pg_repack%';

4. 合理設(shè)計數(shù)據(jù)庫和查詢:

使用分區(qū)表

CREATE TABLE your_table (
    id serial PRIMARY KEY,
    data text
) PARTITION BY RANGE (id);

CREATE TABLE your_table_partition1 PARTITION OF your_table
FOR VALUES FROM (1) TO (1000000);

CREATE TABLE your_table_partition2 PARTITION OF your_table
FOR VALUES FROM (1000001) TO (2000000);

合理設(shè)置填充因子

ALTER TABLE your_table SET (fillfactor = 80);

5. 監(jiān)控和預警:

建立監(jiān)控體系

CREATE OR REPLACE FUNCTION check_table_bloat() RETURNS void AS $$
DECLARE
   r RECORD;
BEGIN
   FOR r IN
       SELECT schemaname, tablename, bloat
       FROM (
           SELECT
               schemaname,
               tablename,
               ROUND(CASE WHEN otta=0 OR relpages=0 OR relpages=otta THEN 0.0 ELSE relpages/otta::numeric END, 2) AS bloat
           FROM (
               SELECT
                   nn.nspname AS schemaname,
                   cc.relname AS tablename,
                   COALESCE(cc.reltuples, 0) AS reltuples,
                   COALESCE(cc.relpages, 0) AS relpages,
                   COALESCE(ce.reltuples, 0) AS expected_reltuples,
                   CASE WHEN ce.reltuples > 0 THEN
                       (cc.reltuples::bigint * cc.rellen)::bigint / (ce.reltuples::bigint * (SELECT setting FROM pg_settings WHERE name='block_size')::int)
                   ELSE
                       0
                   END AS otta
               FROM
                   pg_class cc
                   JOIN pg_namespace nn ON cc.relnamespace = nn.oid
                   LEFT JOIN (
                       SELECT
                           c.relname,
                           c.reltuples,
                           (c.reltuples * (c.rellen + pg_column_size(c.oid, 'ctid') + 24))::bigint AS total_bytes
                       FROM
                           pg_class c
                           LEFT JOIN pg_stat_all_tables s ON c.relname = s.relname
                       WHERE
                           s.schemaname NOT IN ('pg_catalog', 'information_schema')
                           AND c.relkind = 'r'
                   ) ce ON cc.relname = ce.relname
               WHERE
                   nn.nspname NOT IN ('pg_catalog', 'information_schema')
                   AND cc.relkind = 'r'
           ) a
       ) b
       WHERE bloat > 1.0
   LOOP
       RAISE NOTICE 'Schema: %, Table: %, Bloat: %', r.schemaname, r.tablename, r.bloat;
   END LOOP;
END;
$$ LANGUAGE plpgsql;

這個函數(shù)check_table_bloat的目的是檢查PostgreSQL數(shù)據(jù)庫中的表是否存在“膨脹”(bloat)現(xiàn)象,即表占用的磁盤空間是否超過了其實際存儲的數(shù)據(jù)量所需的空間。函數(shù)通過一系列嵌套的查詢來計算每個表的“膨脹率”(bloat),并對于膨脹率大于1.0的表,使用RAISE NOTICE語句輸出相關(guān)信息。

說明

  1. 外層查詢:遍歷所有計算出的膨脹率大于1.0的表,并輸出其模式名(schemaname)、表名(tablename)和膨脹率(bloat)。

  2. 內(nèi)層查詢:計算每個表的膨脹率。這里使用了多個嵌套的子查詢:

    • 第一個子查詢(別名為a)計算了每個表的實際頁數(shù)(relpages)與理想頁數(shù)(otta)的比率,即膨脹率。理想頁數(shù)是根據(jù)表的行數(shù)(reltuples)和每行的大小(rellen)以及塊大?。ㄍㄟ^查詢pg_settings表中的block_size設(shè)置得到)計算出來的。
    • 第二個子查詢(別名為ce)計算了每個表預期的行數(shù)和總字節(jié)數(shù),用于后續(xù)計算理想頁數(shù)。
  3. 過濾條件:排除了系統(tǒng)模式(pg_cataloginformation_schema)和非常規(guī)表(relkind不等于’r’,即不是普通表)。

  4. 函數(shù)定義:使用CREATE OR REPLACE FUNCTION語句定義了一個名為check_table_bloat的函數(shù),該函數(shù)沒有參數(shù),返回類型為void,表示不返回任何值。函數(shù)體使用PL/pgSQL語言編寫。

  5. 循環(huán)和輸出:使用FOR ... IN ... LOOP語句遍歷查詢結(jié)果,并使用RAISE NOTICE語句輸出膨脹信息。

請根據(jù)您的實際數(shù)據(jù)庫環(huán)境和需求,對函數(shù)進行適當?shù)恼{(diào)整和優(yōu)化。這個函數(shù)可以作為數(shù)據(jù)庫維護的一部分,定期運行以檢查并處理表的膨脹問題。

總結(jié)

表膨脹是PostgreSQL數(shù)據(jù)庫中常見的問題,主要表現(xiàn)為表數(shù)據(jù)和索引占用空間不斷增大,而實際數(shù)據(jù)量并未顯著變化。這主要由MVCC機制、頻繁更新刪除、未提交事務、填充因子設(shè)置及autovacuum機制不足等因素引起。膨脹的表會導致存儲成本增加、查詢性能下降、備份恢復時間延長及系統(tǒng)資源消耗增加等問題。為解決這些問題,可以定期執(zhí)行VACUUM操作,啟用和配置autovacuum機制,使用pg_repack或pg_reorg工具進行在線重組,合理設(shè)計數(shù)據(jù)庫和查詢,以及建立監(jiān)控和預警體系。特別是,可以通過創(chuàng)建check_table_bloat函數(shù)來定期檢查表的膨脹情況,并及時采取措施處理,以確保數(shù)據(jù)庫的性能和穩(wěn)定性。

以上就是PostgreSQL表膨脹問題解析及解決方案的詳細內(nèi)容,更多關(guān)于PostgreSQL表膨脹問題的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Postgresql 動態(tài)統(tǒng)計某一列的某一值出現(xiàn)的次數(shù)實例

    Postgresql 動態(tài)統(tǒng)計某一列的某一值出現(xiàn)的次數(shù)實例

    這篇文章主要介紹了Postgresql 動態(tài)統(tǒng)計某一列的某一值出現(xiàn)的次數(shù)實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • PostgreSQL表膨脹問題解析及解決方案

    PostgreSQL表膨脹問題解析及解決方案

    表膨脹是指表的數(shù)據(jù)和索引所占文件系統(tǒng)的空間在有效數(shù)據(jù)量并未發(fā)生大的變化的情況下不斷增大,這種現(xiàn)象會導致關(guān)系文件被大量空洞填滿,從而浪費大量的磁盤空間,本文給大家介紹了PostgreSQL表膨脹問題解析及解決方案,需要的朋友可以參考下
    2024-11-11
  • postgresql數(shù)據(jù)添加兩個字段聯(lián)合唯一的操作

    postgresql數(shù)據(jù)添加兩個字段聯(lián)合唯一的操作

    這篇文章主要介紹了postgresql數(shù)據(jù)添加兩個字段聯(lián)合唯一的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • postgresql?json取值慢的原因分析

    postgresql?json取值慢的原因分析

    這篇文章主要介紹了postgresql json取值為何這么慢,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-06-06
  • PostgreSQL中date_trunc函數(shù)的語法及一些示例

    PostgreSQL中date_trunc函數(shù)的語法及一些示例

    這篇文章主要給大家介紹了關(guān)于PostgreSQL中date_trunc函數(shù)的語法及一些示例的相關(guān)資料,DATE_TRUNC函數(shù)是PostgreSQL數(shù)據(jù)庫中用于截斷日期部分的函數(shù),文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-04-04
  • PostgreSQL 邏輯復制 配置操作

    PostgreSQL 邏輯復制 配置操作

    這篇文章主要介紹了PostgreSQL 邏輯復制 配置操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • 如何在Neo4j與PostgreSQL間實現(xiàn)高效數(shù)據(jù)同步

    如何在Neo4j與PostgreSQL間實現(xiàn)高效數(shù)據(jù)同步

    本文詳細介紹了如何在Neo4j與PostgreSQL兩種數(shù)據(jù)庫之間實現(xiàn)高效數(shù)據(jù)同步,從基礎(chǔ)概念到全量與增量同步的實現(xiàn)策略,結(jié)合具體代碼與實踐案例,為開發(fā)者提供了全面的指導,感興趣的朋友跟隨小編一起看看吧
    2024-12-12
  • PostgreSQL實現(xiàn)按年、月、日、周、時、分、秒的分組統(tǒng)計

    PostgreSQL實現(xiàn)按年、月、日、周、時、分、秒的分組統(tǒng)計

    這篇文章介紹了PostgreSQL實現(xiàn)按年、月、日、周、時、分、秒分組統(tǒng)計的方法,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • PostgreSQL的B-tree索引用法詳解

    PostgreSQL的B-tree索引用法詳解

    這篇文章主要介紹了PostgreSQL的B-tree索引用法詳解,有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • 淺談PostgreSQL的客戶端認證pg_hba.conf

    淺談PostgreSQL的客戶端認證pg_hba.conf

    這篇文章主要介紹了淺談PostgreSQL的客戶端認證pg_hba.conf,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01

最新評論