TOAST Bảng tăng trưởng ngoài tầm kiểm soát - FULLVAC không làm gì cả


9

Gần đây, tôi đã có một máy chủ PostgreSQL 8.2.11 được nâng cấp lên 8.4 để tận dụng các tính năng tự động lưu trữ và phù hợp với 30 máy chủ PGQuery khác. Điều này được thực hiện bởi một nhóm CNTT riêng quản trị phần cứng, vì vậy chúng tôi không có nhiều sự lựa chọn cho bất kỳ nâng cấp nào khác (sẽ không thấy 9+ trong một thời gian nữa). Máy chủ tồn tại trong một môi trường rất kín (mạng bị cô lập, quyền hạn chế gốc) và chạy trên RHEL5.5 (i686). Sau khi nâng cấp, cơ sở dữ liệu đã liên tục phát triển lên mức 5-6 GB mỗi ngày. Thông thường, toàn bộ cơ sở dữ liệu là ~ 20GB; hiện tại, nó là ~ 89GB. Chúng tôi có một vài máy chủ khác chạy cơ sở dữ liệu tương đương và thực sự đồng bộ hóa các bản ghi với nhau thông qua ứng dụng của bên thứ 3 (một máy chủ tôi không có quyền truy cập vào hoạt động bên trong). Các cơ sở dữ liệu khác là ~ 20GB.

Chạy SQL sau, rõ ràng có một vấn đề với một bảng cụ thể và cụ thể hơn là bảng TOAST của nó.

SELECT nspname || '.' || relname AS "relation",
    pg_size_pretty(pg_relation_size(C.oid)) AS "size"
  FROM pg_class C
  LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
  WHERE nspname NOT IN ('pg_catalog', 'information_schema')
  ORDER BY pg_relation_size(C.oid) DESC
  LIMIT 20;

Sản xuất:

              quan hệ | kích thước  
------------------------------------ + ---------  
  pg_toast.pg_toast_16874 | 89 GB  
  fews00.warmstates | 1095 MB  
  ...  
(20 hàng)

Bảng TOAST này dành cho một bảng gọi là "thời gian" giúp lưu các bản ghi lớn của dữ liệu blobbed. Một SUM(LENGTH(blob)/1024./1024.)trong tất cả các bản ghi trong thời gian mang lại ~ 16GB cho cột đó. Không có lý do gì bảng TOAST của bảng này phải lớn như vậy.

Tôi đã thực hiện một VACUUM FULL VERBOSE ANALYZE timeseries, và chân không chạy đến hoàn thành không có lỗi.

INFO: hút bụi "pg_toast.pg_toast_16874"
INFO: "pg_toast_16874": tìm thấy 22483 có thể tháo rời, 10475318 phiên bản
hàng không thể xóa được trong 10448587 trang CHI TIẾT: 0 phiên bản hàng chết chưa thể xóa được.
Các phiên bản hàng không thể xóa được có độ dài từ 37 đến 2036 byte.
Có 20121422 con trỏ mục không sử dụng.
Tổng dung lượng trống (bao gồm các phiên bản hàng có thể tháo rời) là 0 byte. 4944885 trang đang hoặc sẽ trống, bao gồm 0 ở cuối bảng. 4944885 trang chứa 0 byte miễn phí là đích di chuyển tiềm năng.
CPU 75,31s / 29,59u giây trôi qua 877,79 giây.
INFO: index "pg_toast_16874_index" hiện chứa 10475318 phiên bản hàng trong 179931 trang
CHI TIẾT: 23884 phiên bản hàng chỉ mục đã bị xóa.
101623 trang chỉ mục đã bị xóa, 101623 hiện đang được sử dụng lại.
CPU 1,35s / 2,46u giây trôi qua 21,07 giây.

REINDEXed bảng đã giải phóng một số dung lượng (~ 1GB). Tôi không thể CLUSTER bảng vì không có đủ dung lượng trên đĩa cho quy trình và tôi đang chờ để xây dựng lại bảng hoàn toàn vì tôi muốn tìm hiểu lý do tại sao nó lớn hơn nhiều so với cơ sở dữ liệu tương đương chúng ta có.

Chạy một truy vấn từ wiki PostgreQuery tại đây - "Hiển thị cơ sở dữ liệu" và đây là những gì tôi nhận được:

cơ sở dữ liệu hiện tại | schemaname | tablename | tbloat | lãng phí | iname | ibloat | chất thải  
----------------- + ------------ + ------------------- ------------- + -------- + ------------- + ------------- -------------------- + -------- + --------------  
ptrdb04 | vàis00 | thời gian | 1.0 | 0 | idx_timeseries_synchlevel | 0,0 | 0  
ptrdb04 | vàis00 | thời gian | 1.0 | 0 | idx_timeseries_localavail | 0,0 | 0  
ptrdb04 | vàis00 | thời gian | 1.0 | 0 | idx_timeseries_Exirytime | 0,0 | 0  
ptrdb04 | vàis00 | thời gian | 1.0 | 0 | idx_timeseries_Exiry_null | 0,0 | 0  
ptrdb04 | vàis00 | thời gian | 1.0 | 0 | uniq_localintid | 0,0 | 0  
ptrdb04 | vàis00 | thời gian | 1.0 | 0 | pk_timeseries | 0,1 | 0  
ptrdb04 | vàis00 | idx_timeseries_Exiry_null | 0,6 | 0 | ? | 0,0 | 0

Có vẻ như cơ sở dữ liệu không coi không gian này là "trống rỗng", nhưng tôi chỉ không thấy tất cả không gian đĩa đến từ đâu!

Tôi nghi ngờ rằng máy chủ cơ sở dữ liệu này đang quyết định sử dụng 4-5x dung lượng đĩa để lưu các bản ghi tương tự được lấy từ các máy chủ dữ liệu khác. Câu hỏi của tôi là: Có cách nào để tôi xác minh kích thước đĩa vật lý của một hàng không? Tôi muốn so sánh kích thước của một hàng trên cơ sở dữ liệu này với cơ sở dữ liệu "lành mạnh" khác.

Cảm ơn vì bất kì sự giúp đỡ nào của bạn!

CẬP NHẬT 1

Cuối cùng tôi đã xây dựng lại bảng từ một lược đồ bị đổ do kích thước của nó (không thể để nó một mình trong một ngày khác). Sau khi đồng bộ hóa dữ liệu, thông qua quy trình đồng bộ hóa phần mềm, bảng TOAST là ~ 35GB; tuy nhiên, tôi chỉ có thể chiếm ~ 9GB trong số đó từ cột blob đó là giá trị dài nhất về mặt giá trị. Không chắc 26GB khác đến từ đâu. CLUSTERed, VACUUM FULLed và REINDEXed không có kết quả. Các tập tin postgresql.conf giữa các máy chủ dữ liệu cục bộ và từ xa hoàn toàn giống nhau. Có bất kỳ lý do nào cơ sở dữ liệu này có thể đang cố lưu trữ mỗi bản ghi với không gian lớn hơn trên đĩa không?

CẬP NHẬT 2 - Đã sửa

Cuối cùng tôi đã quyết định xây dựng lại hoàn toàn cơ sở dữ liệu từ đầu - thậm chí là cài đặt lại các gói PostgreQuery84 trên hệ thống. Đường dẫn cơ sở dữ liệu đã được khởi tạo lại và không gian bảng bị xóa sạch. Quá trình đồng bộ hóa phần mềm của bên thứ 3 đã lặp lại các bảng và kích thước cuối cùng xuất hiện là ~ 12GB ! Thật không may, điều này, không có cách nào, giúp giải quyết nguồn chính xác của vấn đề ở đây. Tôi sẽ xem nó trong một hoặc hai ngày và xem liệu có bất kỳ sự khác biệt lớn nào với cách cơ sở dữ liệu hồi sinh đang xử lý bảng TOAST và đăng các kết quả đó vào đây không.

Kích thước quan hệ


ptrdb04=> SELECT nspname || '.' || relname AS "relation",
ptrdb04->     pg_size_pretty(pg_relation_size(C.oid)) AS "size"
ptrdb04->   FROM pg_class C
ptrdb04->   LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
ptrdb04->   WHERE nspname NOT IN ('pg_catalog', 'information_schema')
ptrdb04->   ORDER BY pg_relation_size(C.oid) DESC
ptrdb04->   LIMIT 2;

        quan hệ | kích thước   |   kích thước   
------------------------- + ---------------------------------- + ---------
 pg_toast.pg_toast_17269 | 18 GB. pg_toast_17269 | 18 GB 
 fews00.warmstates | 1224 MB. ấm áp        | 1224 MB 
(2 hàng)( 2 hàng ) 

VACUUM VERBOSE ANALYZE timeseries;

THÔNG TIN: "thời gian": tìm thấy 12699 phiên bản hàng rời, 681961 không thể tháo rời trong 58130 trên tổng số 68382 trang
CHI TIẾT: 0 phiên bản hàng chết chưa thể được gỡ bỏ.
Có 105847 con trỏ mục không sử dụng.
0 trang hoàn toàn trống rỗng.
CPU 0,83 giây / 2,08u giây trôi qua 33,36 giây.
THÔNG TIN: hút bụi "pg_toast.pg_toast_17269"
THÔNG TIN: chỉ mục được quét "pg_toast_17269_index" để xóa 2055849 phiên bản hàng
CHI TIẾT: CPU 0,37s / 2,92u giây trôi qua 13,29 giây.
THÔNG TIN: "pg_toast_17269": đã xóa 2055849 phiên bản hàng trong 518543 trang
CHI TIẾT: CPU 8,60 giây / 3,21u giây trôi qua 358,42 giây.
THÔNG TIN: chỉ mục "pg_toast_17269_index" hiện có 7346902 phiên bản hàng trong 36786 trang
CHI TIẾT: 2055849 phiên bản hàng chỉ mục đã bị xóa.
10410 trang chỉ mục đã bị xóa, 5124 hiện có thể tái sử dụng.
CPU 0,00 giây / 0,00u giây trôi qua 0,01 giây.
THÔNG TIN: "pg_toast_17269": đã tìm thấy 1286128 có thể tháo rời, 2993389 phiên bản hàng không thể xóa được trong 1257871 trên 2328079 trang
CHI TIẾT: 0 phiên bản hàng chết chưa thể được gỡ bỏ.
Có 18847 con trỏ mục không sử dụng.
0 trang hoàn toàn trống rỗng.
CPU 26,56s / 13,04u giây trôi qua 714,97 giây.
THÔNG TIN: phân tích "fews00.timeseries"
THÔNG TIN: "thời gian": quét 30000 trên 68382 trang, chứa 360192 hàng sống và 0 hàng chết; 30000 hàng trong mẫu, 821022 tổng số hàng ước tính

Sự khác biệt đáng chú ý duy nhất sau khi xây dựng lại (trừ sử dụng đĩa) là

THÔNG TIN: "pg_toast_17269": đã tìm thấy 1286128 có thể tháo rời, 2993389 phiên bản hàng không thể di chuyển
như @CraigRinger đã đề cập trong một bình luận. Số lượng hàng không thể thay đổi nhỏ hơn nhiều so với trước đây.

Câu hỏi mới: Các bảng khác có thể ảnh hưởng đến kích thước của một bảng khác không? (thông qua các khóa ngoại và như vậy) Việc xây dựng lại bảng không làm gì cả, nhưng việc xây dựng lại toàn bộ cơ sở dữ liệu đã được chứng minh là đã khắc phục vấn đề.


Tại sao bạn không nâng cấp thẳng lên 9.2? Nó thậm chí còn có nhiều cải tiến hơn trong khu vực
tiêm chủng

Tôi đã cập nhật bài viết. Nâng cấp không được thực hiện bởi cửa hàng của chúng tôi và không nhất thiết phải theo yêu cầu của chúng tôi. Thật không may, chúng tôi không có tùy chọn đó để nâng cấp lên 9+.
BrM13

ĐỒNG Ý. Tôi chỉ muốn chắc chắn rằng bạn không nhìn rõ ràng;)
a_horse_with_no_name

Câu trả lời:


9

Điều này:

INFO: "pg_toast_16874": found 22483 removable, 10475318 nonremovable row versions in 10448587 pages 22483 removable, 10475318 nonremovable row versions in 10448587 pages

đề xuất rằng vấn đề cơ bản là một cái gì đó vẫn có thể "nhìn thấy" những hàng đó để chúng không thể bị xóa.

Các ứng cử viên cho điều đó là:

  • Mất giao dịch chuẩn bị. Kiểm tra pg_catalog.pg_prepared_xacts; nó nên trống rỗng Cũng chạy SHOW max_prepared_transactions; nó nên báo cáo bằng không.

  • Các phiên chạy dài với một giao dịch mở, nhàn rỗi. Trong PostgreQuery 8.4 trở lên, đây chỉ là một vấn đề đối với SERIALIZABLEcác giao dịch. Kiểm tra pg_catalog.pg_stat_activitycho <IDLE> in transactionphiên.

Nhiều khả năng bạn có một khách hàng không thực hiện giao dịch hoặc cam kết trong thời gian nhàn rỗi dài.

Nếu điều này không thành ra, điều tiếp theo tôi sẽ kiểm tra là thực hiện tổng số octet_sizetừng cột của bảng quan tâm. So sánh với pg_relation_sizebảng và bảng TOASTphụ của nó . Nếu có sự khác biệt lớn thì không gian tiêu thụ có thể sẽ không còn xuất hiện ở các hàng và bạn có thể gặp sự cố phình bảng. Nếu chúng khá giống nhau, bạn có thể bắt đầu thu hẹp nơi sử dụng không gian bằng cách tổng hợp các kích thước bát phân trên mỗi cột, nhận các giá trị hàng đầu, v.v.


1) pg_prepared_xacts và max_prepared_transilities thực sự đã trở lại trống rỗng. 2) Chắc chắn có một số giao dịch IDLE từ SELECT * FROM pg_stat_activity WHERE current_query LIKE '<IDLE>%';đó mang lại khoảng 30-40 kết quả; Tuy nhiên, điều này có vẻ khá bình thường. Tôi đã kiểm tra một vài máy chủ "khỏe mạnh" và chúng giống nhau.
BrM13

3) Đây là những gì tôi đã làm. Lặp lại qua các cột thời gian, kéo octet_length (cột). Nhân từng giá trị theo số hàng và tính tổng chúng. Đối với thời gian, tôi nhận được ~ 430 MB (gần với 493 MB từ pg_relation_size) và 438 MB cho bảng TOAST (sử dụng các cột chunk_id, chunk_seq, chunk_data). Các ước tính có vẻ chính xác và bảng TOAST bị loại bỏ mối quan hệ với khoảng 2 đơn hàng độ lớn (60GB ngày nay). Có vẻ như tôi có sự phình to, nhưng không phải là loại truyền thống (không sử dụng phình to). Nếu không, FULLVAC sẽ giải quyết vấn đề.
BrM13

Các phiên @Brad không hoạt động , chỉ các phiên nhàn rỗi với các giao dịch mở là một vấn đề, nghĩa là <IDLE> in transactionvà chỉ khi chúng (a) không hoạt động trong một thời gian và (b) đang sử dụng SERIALIZABLEcách ly hoặc bạn đang ở trên 8.3 hoặc lớn hơn.
Craig Ringer

@Brad Thật thú vị khi chỉ có TOASTbảng dường như bị cồng kềnh. BTW, nếu bạn đã sử dụng VACUUM FULLnhiều trên máy chủ trước 9.0, bạn sẽ muốn REINDEXnhư VACUUM FULLtrên các phiên bản đó có thể gây ra sự phình to chỉ số đáng kể. Bây giờ tôi đang tự hỏi nếu ai đó đặt một cái vô lý FILLFACTORtrên bàn bánh mì nướng, mặc dù điều đó không cho phép bạn vượt qua mức tiêu thụ không gian gấp 10 lần.
Craig Ringer

Cảm ơn đã làm rõ IDLE. Tôi đoán đó là những gì bạn muốn nói, nhưng thật tốt khi biết điều đó. Đối với FILLFACTOR, bảng đang sử dụng mặc định. FYI - Theo tài liệu 8.4 CREATE TABLE , mặc định là 100 và bạn không thể đặt FILLFACTOR cho bảng TOAST.
BrM13

0

Tôi không có cái nhìn sâu sắc về lý do tại sao nó cồng kềnh. Nhưng tôi đã thực hiện một số tìm kiếm và có thể liên kết này có một số thông tin chi tiết: http://postgresql.1045698.n5.nabble.com/A-154-GB-table-swelling-to-527-GB-on-the-Slony-slave -How-to-compact-it-td5543034.html ... Đây không phải là tình huống chính xác của bạn nhưng có lẽ nó đủ gần để giúp bạn đi đến tận cùng của phình to.

Tuy nhiên, tôi nghĩ cách duy nhất để thu gọn bảng đó vào thời điểm này là CLUSTER nó. Vì bạn không đủ dung lượng đĩa, đó là một vấn đề.

Đây là gợi ý của tôi cho điều đó: tạo một không gian bảng trên một ổ đĩa khác có nhiều không gian thừa, sau đó gán bảng vấn đề của bạn cho không gian bảng đó. PostgreSQL sẽ sao chép bảng sang không gian bảng mới (có thể khóa bảng trong quy trình, vì vậy bạn sẽ cần một cửa sổ bảo trì). Sau đó VACFULL bảng (xóa hầu hết không gian cũ được sử dụng bởi bảng trong không gian bảng mặc định). Sau đó CLUSTER bảng và nó sẽ tự nén. Sau đó đặt nó trở lại trong không gian bảng mặc định và chạy lại VACFULL (để xóa không gian chưa sử dụng trong không gian bảng mới).


Tôi thực sự đã kết thúc việc xây dựng lại bảng (bỏ lược đồ và xây dựng lại từ đó) và lấy dữ liệu trực tiếp từ một trong các cơ sở dữ liệu từ xa. Sau khi quá trình hoàn tất, cơ sở dữ liệu vẫn là 35 GB với chỉ 9 GB được tính bằng cột "rộng". CLUSTERed, VACUUM FULLed, REINDEXed, và tôi vẫn đang ngồi trên một tấn sử dụng đĩa bí ẩn.
BrM13

Liên kết đã chết :(
hayd
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.