2012-12-18 26 views
7

Chúng tôi có một sản phẩm sử dụng máy chủ cơ sở dữ liệu PostgreSQL được triển khai tại một vài trăm máy khách. Một số người trong số họ đã thu thập hàng chục gigabyte dữ liệu trong những năm qua. Vì vậy, trong phiên bản tiếp theo, chúng tôi sẽ giới thiệu các quy trình làm sạch tự động sẽ dần dần lưu trữ và DELETE hồ sơ cũ trong các công việc hàng loạt hàng đêm.PostgresQL Tự động VACUUM ĐẦY ĐỦ cho các bảng cồng kềnh

Nếu tôi hiểu chính xác, autovacuum sẽ bắt đầu và phân tích và tổ chức lại các bộ dữ liệu, do đó hiệu suất sẽ giống như khi có ít bản ghi hơn.

Không gian đĩa thực tế sẽ không được phát hành, nếu tôi hiểu đúng, vì đó chỉ xảy ra với một CHÂN KHÔNG ĐẦY ĐỦ, và đó không phải được kích hoạt bởi autovacuum.

Vì vậy, tôi đã suy nghĩ về một quy trình tự động sẽ thực hiện việc này.

Tôi đã tìm thấy chế độ xem bloat được sử dụng bởi nagios check_postgres tại http://wiki.postgresql.org/wiki/Show_database_bloat.

Chế độ xem này có tốt không? Tôi có đúng khi hiểu rằng nếu tbloat là> 2, nó có thể sử dụng VACUUM FULL không? Và nếu ibloat quá cao, nó có thể sử dụng REINDEX không?

Bất kỳ nhận xét nào về công việc sau để chạy như công việc hàng ngày?

  • vacuumdb -Z mydatabase #vacuum với phân tích chỉ
  • select tablename from bloatview order by tbloat desc limit 1
  • vacuumdb -f -t tablename mydatabase
  • select tablename, iname from bloatview order by ibloat desc limit 1
  • reindexdb -t tablename -i iname mydatabase

Tắt Tất nhiên, tôi vẫn cần phải quấn nó trong một kịch bản perl ngơi thoải mái tại crontab (chúng tôi đang sử dụng ubuntu 12), hoặc không postgresql có một số loại của scheduler tôi có thể làm điều này với?

Hoặc là tổng số quá mức cần thiết này và có quy trình đơn giản hơn nhiều không?

+0

vacuumdb -Z có lẽ là không cần thiết, autovacuum dường như làm một công việc khá tốt để giữ phân tích được cập nhật. – greyfairer

Trả lời

4

Có thể bạn don' Tôi cần nó. Bạn nên làm điều này một lần - sau lần lưu trữ đầu tiên, vì vậy bạn sẽ lấy lại được dung lượng đĩa, nhưng sau đó công việc lưu trữ hàng ngày và autovacuum của bạn sẽ ngăn chặn các tuples chết.

Cũng thay vì vacuum full, thường tốt hơn là chạy cluster table_name using index_name; analyze table_name.Điều này sẽ sắp xếp lại các hàng theo một chỉ mục. Bằng cách này, các hàng trong bảng có liên quan có thể được lưu trên đĩa, có thể hạn chế tìm kiếm đĩa (quan trọng trên ổ đĩa cổ điển, phần lớn không liên quan trên SSD) và một số lần đọc cho các truy vấn thông thường của bạn.

Và hãy nhớ rằng cả hai vacuum fullcluster sẽ làm cho bảng của bạn không sử dụng được trong khi chúng chạy.

+0

Cảm ơn gợi ý. Quá trình dọn dẹp chúng tôi giới thiệu sẽ được lên kế hoạch để chạy trong vài giờ vào ban đêm, nhưng sẽ mất vài đêm tại một số khách hàng trước khi nó kết thúc. Tôi đồng ý tốt hơn là đợi cho đến khi dọn dẹp hoàn thành xong, và sau đó làm chân không đầy hoặc cụm chỉ một lần trong thời gian ngừng hoạt động theo lịch trình. Chỉ chúng tôi có 200 cài đặt mà chúng tôi cần để lên lịch cho điều này, đó là lý do tại sao chúng tôi muốn tự động hóa. Cảm ơn gợi ý về CLUSTER. – greyfairer

+0

Từ Postgresql 9.0 trở lên tối ưu hóa trên 'VACUUM FULL' đã làm cho nó là cách thích hợp để làm điều đó. (xem: https://wiki.postgresql.org/wiki/VACUUM_FULL#CLUSTER) –

3

OK, tôi đã làm việc theo cách của mình.

tôi đơn giản hóa/làm lại quan điểm để tách nó ra trong những điều sau hai:

CREATE OR REPLACE VIEW 
    bloat_datawidth AS 
SELECT 
    ns.nspname AS schemaname, 
    tbl.oid AS relid, 
    tbl.relname, 
    CASE 
     WHEN every(avg_width IS NOT NULL) 
     THEN SUM((1-null_frac)*avg_width) + MAX(null_frac) * 24 
     ELSE NULL 
    END AS datawidth 
FROM 
    pg_attribute att 
JOIN 
    pg_class tbl 
ON 
    att.attrelid = tbl.oid 
JOIN 
    pg_namespace ns 
ON 
    ns.oid = tbl.relnamespace 
LEFT JOIN 
    pg_stats s 
ON 
    s.schemaname=ns.nspname 
AND s.tablename = tbl.relname 
AND s.inherited=false 
AND s.attname=att.attname 
WHERE 
    att.attnum > 0 
AND tbl.relkind='r' 
GROUP BY 
    1,2,3; 

CREATE OR REPLACE VIEW 
    bloat_tables AS 
SELECT 
    bdw.schemaname, 
    bdw.relname, 
    bdw.datawidth, 
    cc.reltuples::bigint, 
    cc.relpages::bigint, 
    ceil(cc.reltuples*bdw.datawidth/current_setting('block_size')::NUMERIC)::bigint AS expectedpages, 
    100 - (cc.reltuples*100*bdw.datawidth)/(current_setting('block_size')::NUMERIC*cc.relpages) AS bloatpct 
FROM 
    bloat_datawidth bdw 
JOIN 
    pg_class cc 
ON 
    cc.oid = bdw.relid 
AND cc.relpages > 1 
AND bdw.datawidth IS NOT NULL; 

Và công việc cron:

#!/bin/bash 

MIN_BLOAT=65 
MIN_WASTED_PAGES=100 
LOG_FILE=/var/log/postgresql/bloat.log 
DATABASE=unity-stationmaster 
SCHEMA=public 

if [[ "$(id -un)" != "postgres" ]] 
then 
echo "You need to be user postgres to run this script." 
exit 1 
fi 

TABLENAME=`psql $DATABASE -t -A -c "select relname from bloat_tables where bloatpct > $MIN_BLOAT and relpages-expectedpages > $MIN_WASTED_PAGES and schemaname ='$SCHEMA' order by wastedpages desc limit 1"` 

if [[ -z "$TABLENAME" ]] 
then 
echo "No bloated tables." >> $LOG_FILE 
exit 0 
fi 

vacuumdb -v -f -t $TABLENAME $DATABASE >> $LOG_FILE 
Các vấn đề liên quan