Trong Postgres-XL, các chuỗi được duy trì tại Trình quản lý giao dịch toàn cầu (GTM) để đảm bảo rằng chúng được gán các giá trị không xung đột khi chúng được tăng lên từ nhiều nút. Điều này bổ sung thêm chi phí đáng kể cho một truy vấn thực hiện hàng nghìn INSERT trong một bảng có cột nối tiếp, tăng dần trình tự từng lần một và tạo vòng lặp mạng cho GTM, cho mỗi INSERT.
Shaun Thomas trong một blog gần đây đã phàn nàn về việc INSERT chạy chậm hơn nhiều trên Postgres-XL so với PostgreSQL vani. Đã có một cách để cải thiện hiệu suất cho các chuỗi, nhưng rõ ràng nó không được quảng cáo tốt. Tôi nghĩ đây là một cơ hội tốt để giải thích về cơ sở này.
Postgres-XL cung cấp GUC do người dùng thiết lập được gọi là dãy_mạch . Mọi phụ trợ đều yêu cầu một khối giá trị trình tự do GUC này điều khiển. Do COPY được sử dụng phổ biến để tải dữ liệu hàng loạt trong Postgres, Postgres-XL tự động ghi đè GUC này trong quá trình hoạt động COPY và đặt nó thành 1000, do đó cải thiện đáng kể hiệu suất COPY. Thật không may, đối với INSERT thông thường, giá trị mặc định là 1 và trừ khi người dùng đặt rõ ràng chuỗi_mảng đến một giá trị cao hơn hợp lý, hiệu suất INSERT sẽ bị ảnh hưởng. Đây là một ví dụ, sử dụng cùng một lược đồ mẫu được Shaun sử dụng trong bài đăng trên blog của anh ấy.
CREATE TABLE sensor_log ( sensor_log_id SERIAL PRIMARY KEY, location VARCHAR NOT NULL, reading BIGINT NOT NULL, reading_date TIMESTAMP NOT NULL ) DISTRIBUTE BY HASH (sensor_log_id); postgres=# \timing Timing is on. postgres=# INSERT INTO sensor_log (location, reading, reading_date) SELECT s.id % 1000, s.id % 100, now() - (s.id || 's')::INTERVAL FROM generate_series(1, 40000) s(id); INSERT 0 40000 Time: 12067.911 ms postgres=# set sequence_range TO 1000; SET Time: 1.231 ms postgres=# INSERT INTO sensor_log (location, reading, reading_date) SELECT s.id % 1000, s.id % 100, now() - (s.id || 's')::INTERVAL FROM generate_series(1, 40000) s(id); INSERT 0 40000 Time: 397.406 ms
Vì vậy, bằng cách thiết lập thích hợp dãy_mạch lên 1000, hiệu suất của truy vấn INSERT được cải thiện gần 30 lần.
Khi tính năng này được thêm vào, giá trị mặc định của GUC theo dãy_được đặt thành 1 vì nó có thể để lại lỗ hổng trong các giá trị dãy. Nhưng xem xét các tác động về hiệu suất đối với một trường hợp sử dụng rất phổ biến, chúng tôi quyết định tăng giá trị mặc định lên 1000 và điều này hiện đã được cam kết với nhánh XL9_5_STABLE của kho lưu trữ.
Điều quan trọng cần lưu ý là mặc dù giá trị cao của chuỗi_mảng sẽ cải thiện hiệu suất cho các trình tự và nối tiếp, nó cũng có thể để lại các lỗ hổng lớn trong các phạm vi trình tự vì các phạm vi trình tự được lưu vào bộ nhớ đệm ở cấp phụ trợ. Để giải quyết vấn đề này, Postgres-XL bắt đầu với giá trị tham số CACHE được chỉ định được sử dụng tại thời điểm tạo trình tự và nhân đôi giá trị này mọi lúc (giới hạn bởi chuỗi_mảng) nếu chuỗi đang được sử dụng với tốc độ rất cao.
Cải thiện tương tự cũng có thể đạt được bằng cách tăng giá trị tham số CACHE của trình tự để một phần giá trị trình tự được lưu vào bộ nhớ đệm ở cấp phụ trợ. Ví dụ sau đây cho thấy cách thực hiện điều đó cho một cột nối tiếp. Nhưng dãy_mạch GUC cung cấp một cách dễ dàng để ghi đè mặc định chung và cũng đảm bảo rằng các chuỗi chỉ được lưu vào bộ nhớ đệm khi chúng đang tăng lên rất nhanh.
postgres=# ALTER SEQUENCE sensor_log_sensor_log_id_seq CACHE 1000; ALTER SEQUENCE Time: 8.683 ms postgres=# SET sequence_range TO 1; SET Time: 2.341 ms postgres=# INSERT INTO sensor_log (location, reading, reading_date) SELECT s.id % 1000, s.id % 100, now() - (s.id || 's')::INTERVAL FROM generate_series(1, 40000) s(id); INSERT 0 40000 Time: 418.068 ms
Bạn có thể chọn bất kỳ kỹ thuật nào trong số này để cải thiện hiệu suất. Mặc dù bây giờ là giá trị mặc định của dãy_mạch được thay đổi thành 1000, không nhiều người dùng có thể thấy sự khác biệt về hiệu suất.