Thiết kế phân cấp phân vùng PostgreSQL để ghi nhật ký tập trung


7

Tôi đang xem xét việc thiết lập đăng nhập từ tất cả các máy chủ của tôi vào cơ sở dữ liệu postgresql tập trung. Thật ý nghĩa khi có thể thả nhật ký theo ngày hoặc theo máy chủ, vì vậy tôi muốn thiết lập nó với phân vùng , nhưng phân vùng nhiều lớp:host-service inherits service, host-service-yyyymm inherits host-service.

Tôi đã xây dựng một sơ đồ ví dụ cho một dịch vụ cụ thể (lỗi php trong trường hợp này) và đang tìm kiếm một số chuyên gia PostgreQuery để phê bình nó về các tắc nghẽn hiệu suất rõ ràng.

// SET UP MASTER PHP LOG TABLE //
CREATE TABLE php (
 log_id     int not null,
 host       char(5),    
 logdate     date not null,
 message        text
);

// SET UP HOST-SPECIFIC 'PARTITIONS' //
CREATE TABLE host1_php (
 CHECK ( host = 'host1' )
) INHERITS (php);

CREATE TABLE host2_php (
 CHECK ( host = 'host2' )
) INHERITS (php);

// SET UP HOST-SPECIFIC TIME 'PARTITIONS' //
CREATE TABLE host1_php_2011m12 (
 CHECK ( logdate >= DATE '2011-12-01' AND logdate < DATE '2012-01-01' )
) INHERITS (host1_php);

CREATE TABLE host1_php_2012m01 (
 CHECK ( logdate >= DATE '2012-01-01' AND logdate < DATE '2012-02-01' )
) INHERITS (host1_php);

CREATE TABLE host2_php_2011m12 (
 CHECK ( logdate >= DATE '2011-12-01' AND logdate < DATE '2012-01-01' )
) INHERITS (host2_php);

CREATE TABLE host2_php_2012m01 (
 CHECK ( logdate >= DATE '2012-01-01' AND logdate < DATE '2012-02-01' )
) INHERITS (host2_php);

CREATE INDEX host1_php_2011m12_logdate ON host1_php_2011m12 (logdate);
CREATE INDEX host1_php_2012m01_logdate ON host1_php_2012m01 (logdate);
CREATE INDEX host2_php_2011m12_logdate ON host2_php_2011m12 (logdate);
CREATE INDEX host2_php_2012m01_logdate ON host2_php_2012m01 (logdate);

Tôi cũng sẽ thêm các dịch vụ như truy cập / lỗi apache.

Tôi nghĩ rằng tôi phải kích hoạt để chèn vào host_service (để sử dụng ràng buộc kiểm tra máy chủ) và sau đó mỗi host_service phải kích hoạt để chèn vào bảng host_service_yyyymm.

Tôi có thể mong đợi gì về hiệu năng của lược đồ kích hoạt / phân vùng như vậy?

Một số thông tin bổ sung được thảo luận trong trò chuyện:

  • Phiên bản PostgreSQL 9.1.2
  • Các truy vấn về dữ liệu sẽ không thường xuyên và chủ yếu vào tháng dữ liệu hiện tại cho nhiều máy chủ.
  • PHP chỉ được chèn khoảng 1 mỗi phút, nhưng tổng số apache có thể sẽ vào khoảng 300-500 mỗi giây trên tất cả các máy chủ.

Này @DTest. Tôi nhìn vào công cụ của bạn và nghĩ lại những ngày MRG_MyISAM của tôi. Vì tôi là người mới làm quen với PostgresSQL, đây là một câu hỏi thường gặp: phpBảng có cần một chỉ mục trên (host,logdate)và trẻ em có kế thừa chỉ mục không?
RolandoMySQLDBA

Hah, MERGEchính xác là những gì tôi nghĩ khi đọc về phân vùng trong Postgre ... Không, không có chỉ mục nào trên bản gốc
Derek Downey

1
Kiểm tra CREATE INDEXbáo cáo của bạn . Không phải chúng nên là các bảng khác nhau, một bảng cho mỗi phân vùng?
RolandoMySQLDBA

Câu trả lời:


6

Tôi có thể mong đợi gì về hiệu năng của lược đồ kích hoạt / phân vùng như vậy?

Chuyển đổi ngữ cảnh có nghĩa là sử dụng kích hoạt sẽ luôn sử dụng nhiều CPU hơn là đơn giản insert. Kịch bản dưới đây có thể được sử dụng để định lượng mức độ ảnh hưởng sẽ có - và cũng thể hiện các phân vùng tự động tạo bằng cách sử dụng kích hoạt và so sánh hiệu suất theo bất kỳ cách nào.

Xin lưu ý rằng tôi chưa bao gồm bất kỳ lập chỉ mục, hoặc bất kỳ xem xét các updatetuyên bố.

begin; 
set role dba;
create role stack;
grant stack to dba;
create schema authorization stack;
set role stack;
--
--******** the above creates a nice clean schema as a test area
--
set client_min_messages to warning; --******** or you get a lot of "NOTICE:  merging column "xyz" with inherited definition" notices
--
create table phpheap(log_id serial not null, host text not null, logdate date not null, message text not null); --******** This table is used to compare 'insert' performance with that on the partitioned version
create table php(log_id serial not null, host text not null, logdate date not null, message text not null);
--
create function php_host_insert() returns trigger language plpgsql security definer as $$
begin 
  set search_path to 'stack';
  execute 'insert into php_'||new.host||'_'||to_char(new.logdate, 'YYYYmMM')||'(log_id, host, logdate, message) values($1, $2, $3, $4)' using new.log_id, new.host, new.logdate, new.message;
  return null;
exception when undefined_table then
  execute 'create table php_'||new.host||'_'||to_char(new.logdate, 'YYYYmMM')||'(log_id int not null, host text not null check(host='''||new.host||'''), logdate date not null check(to_char(logdate, ''YYYYmMM'')='''||to_char(new.logdate, 'YYYYmMM')||'''), message text not null) inherits (php_'||new.host||')';
  execute 'insert into php_'||new.host||'_'||to_char(new.logdate, 'YYYYmMM')||'(log_id, host, logdate, message) values($1, $2, $3, $4)' using new.log_id, new.host, new.logdate, new.message;
  return null;
end;$$;
--
create function php_insert() returns trigger language plpgsql security definer as $$
begin 
  set search_path to 'stack';
  execute 'insert into php_'||new.host||'(log_id, host, logdate, message) values($1, $2, $3, $4)' using new.log_id, new.host, new.logdate, new.message;
  return null; 
exception when undefined_table then
  execute 'create table php_'||new.host||'(log_id int not null, host text not null check(host='''||new.host||'''), logdate date not null, message text not null) inherits(php)';
  execute 'create trigger trig_insert_php_'||new.host||' before insert on php_'||new.host||' for each row execute procedure php_host_insert()';
  execute 'insert into php_'||new.host||'(log_id, host, logdate, message) values($1, $2, $3, $4)' using new.log_id, new.host, new.logdate, new.message;
  return null;
end;$$;
--
create trigger trig_insert_php before insert on php for each row execute procedure php_insert();
--
\timing on
insert into phpheap(host, logdate, message) select 'host1', current_date-(generate_series(-99999, 0, 1)/1000)::integer, repeat('hello',20);
--******** output
--INSERT 0 100000
--Time: 1102.140 ms
insert into php(host, logdate, message) select 'host1', current_date-(generate_series(-99999, 0, 1)/1000)::integer, repeat('hello',20);
--******** output
--INSERT 0 0
--Time: 35615.498 ms
insert into php(host, logdate, message) select 'host1', current_date-(generate_series(-99999, 0, 1)/1000)::integer, repeat('hello',20);
--******** output
--INSERT 0 0
--Time: 34074.579 ms
\timing off
--
--******** Now we replace the trigger functions with the 'normal' kind that don't auto-create partitions
--
create or replace function php_host_insert() returns trigger language plpgsql security definer as $$
begin 
  set search_path to 'stack';
  execute 'insert into php_'||new.host||'_'||to_char(new.logdate, 'YYYYmMM')||'(log_id, host, logdate, message) values($1, $2, $3, $4)' using new.log_id, new.host, new.logdate, new.message;
  return null;
end;$$;
--
create or replace function php_insert() returns trigger language plpgsql security definer as $$
begin 
  set search_path to 'stack';
  execute 'insert into php_'||new.host||'(log_id, host, logdate, message) values($1, $2, $3, $4)' using new.log_id, new.host, new.logdate, new.message;
  return null; 
end;$$;
--
\timing on
insert into php(host, logdate, message) select 'host1', current_date-(generate_series(-99999, 0, 1)/1000)::integer, repeat('hello',20);
--******** output
--INSERT 0 0
--Time: 28457.146 ms
\timing off
--
rollback;

Cám ơn vì cái này. Vẫn chơi với các ý tưởng, nhưng tôi có thể thực hiện một đống cho việc thu thập nhật ký và sau đó phân tích chúng thành một thiết lập được phân vùng với thông tin bổ sung được thu thập từ cột thông báo mỗi ngày một lần.
Derek Downey
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.