23 cách nữa để tăng tốc Firebird
Alexey Kovyazin, IBSurgeon, [email protected], 08-Thg1-2019
Bản dịch: Portuguese
Tại sao là “23 cách nữa”?
Một số bạn còn nhớ bài viết « 45 Cách Tăng Tốc Firebird», được xuất bản vào tháng 5 năm 2016. Bây giờ là lúc để xuất bản loạt mẹo và thủ thuật tiếp theo, chủ yếu dựa trên kinh nghiệm tối ưu hóa và bảo trì các cơ sở dữ liệu và máy chủ Firebird với số lượng kết nối cao (1000+).
1. Đặt Tùy chọn Nguồn điện ở chế độ Hiệu suất Cao trong Windows Server 2016 và 2019
Theo mặc định, Windows Server có gói nguồn điện được đặt ở chế độ “Cân bằng”, không phù hợp cho máy chủ cơ sở dữ liệu. Hãy đặt nó ở chế độ “Hiệu suất Cao” và đạt được khoảng +20% hiệu suất cho các hoạt động sử dụng nhiều CPU. Có thể thiết lập trực tuyến mà không cần khởi động lại. Hình dưới đây cho thấy biểu đồ CPU, minh họa lợi thế của gói nguồn điện “Hiệu suất cao”:

Chi tiết hơn về các thử nghiệm của chúng tôi với các gói nguồn điện Windows có thể tìm thấy tại đây.
2. Bật «Tương tác với màn hình» trên Classic cho Windows
Nếu bạn đang sử dụng Firebird với kiến trúc Classic trên Windows, hãy bật dấu kiểm «Cho phép dịch vụ tương tác với màn hình». Nếu không có thiết lập này, tài nguyên «desktop heap» bị giới hạn bởi Windows, và Firebird không thể mở quá 250-300 kết nối (phụ thuộc vào metadata của cơ sở dữ liệu và mức tiêu thụ bộ nhớ liên quan) - sẽ có lỗi Out Of Memory.

3. Cẩn thận: Domain Controller
Vấn đề là Windows với vai trò Domain Controller vô hiệu hóa bộ nhớ đệm ghi trên ổ đĩa chứa cơ sở dữ liệu Active Directory.
Điều này ảnh hưởng đến Firebird theo nhiều cách khác nhau (cũng như các ứng dụng khác, tất nhiên), và nó cho thấy hiệu suất kém hơn đáng kể so với các máy chủ không có vai trò Active Directory.
Xin lưu ý rằng vấn đề này ảnh hưởng đến các phiên bản Windows phổ biến như Windows Small Business Server 2011, cũng như các phiên bản khác có DC.
4. Tăng giới hạn «max open files» trên Linux
Nếu bạn đang sử dụng Linux làm máy chủ cơ sở dữ liệu, đừng quên điều chỉnh các giới hạn cho Firebird. Kiểm tra giới hạn cho tiến trình Firebird của bạn (SuperServer hoặc SuperClassic) bằng lệnh sau:
cat /proc//limits
và chú ý đến dòng có số lượng tối đa các tệp mở.
Firebird có thể sử dụng tối đa 4 handle cho mỗi kết nối, và nếu bạn thấy điều gì đó như thế này:
Max open files 4096 4096 files
điều đó có nghĩa là tổng số kết nối được phục vụ bởi tiến trình Firebird sẽ bị giới hạn ở khoảng 1000.
Xin lưu ý - nếu bạn có 4 cơ sở dữ liệu trên máy chủ, kết nối cho mỗi cơ sở dữ liệu đều được tính.
Hãy đặt nhiều hơn - tôi khuyên dùng 65535.
Đừng quên kiểm tra lại sau khi khởi động lại tiến trình Firebird: xem nó đã được áp dụng hay chưa.
Đối với kiến trúc Classic, cần kiểm tra và tăng giới hạn cho người dùng «firebird».
5. Sử dụng Linux hiện đại
Vâng, tôi hiểu rằng lời khuyên này là tầm thường, nhưng tôi đã thấy nhiều lần sự cải thiện hiệu suất tốt sau khi di chuyển từ CentOS 6 lên 7, Ubuntu 12 lên 16 (trên cùng một phần cứng!), vì vậy bây giờ đây là khuyến nghị bắt buộc cho các máy chủ cơ sở dữ liệu có hơn 250-300 kết nối. Linux hiện đại là điều kiện tiên quyết trước các bước tối ưu hóa tiếp theo.
Các phiên bản Linux được khuyến nghị: CentOS 7.x và Ubuntu 16, 18.
6. Dành riêng 40% RAM cho bộ nhớ đệm tệp trên Windows
Trình quản lý bộ nhớ của HĐH có những tác động liên quan đến việc phân bổ bộ nhớ, và theo mặc định, Windows yêu cầu 40% RAM cho bộ nhớ đệm tệp.
Thật không may, công cụ kém chất lượng Windows Task Manager hiển thị bộ nhớ được sử dụng cho bộ nhớ đệm tệp là «trống», và một số quản trị viên cố gắng làm cho Firebird tiêu thụ tất cả bộ nhớ trống này, vì vậy họ đặt tham số DefaultDBCachePage trong firebird.conf ở giá trị rất cao, và điều này thường dẫn đến swapping.
Luôn sử dụng công cụ RAMMap để xem mức sử dụng bộ nhớ thực tế trên Windows.
Quy tắc kinh nghiệm cho Windows Server (dành riêng để sử dụng làm máy chủ Firebird) như sau: bộ nhớ Firebird (Working Set) phải nhỏ hơn 40% tổng RAM. Nếu tổng kích thước working set cho tất cả các tiến trình lớn hơn 50%, Windows có thể bắt đầu swap.
Xin lưu ý: “dành riêng” ở đây không chỉ có nghĩa là “không đặt quá nhiều page buffer trong Firebird” mà còn, quan trọng là, hạn chế mức sử dụng bộ nhớ của phần mềm khác. Ví dụ: nếu bạn có MS Exchange hoặc MSSQL trên cùng máy chủ với Firebird, hãy đảm bảo hạn chế nhu cầu bộ nhớ của chúng.
Nếu bạn quan tâm đến chi tiết, tôi đã ghi lại webinar dành riêng cho việc quản lý bộ nhớ trong Firebird:
- Phần 1. https://www.youtube.com/watch?v=ZBmLgbYt4aM
- Phần 2, https://www.youtube.com/watch?v=-1.DF2FnU-A
7. Dành riêng 30% RAM cho bộ nhớ đệm tệp trên Linux
Linux hoạt động với bộ nhớ đệm tệp theo cách khác với Windows, và nói chung, lượng RAM được sử dụng cho bộ nhớ đệm tệp có thể ít hơn đáng kể so với Windows mà không làm suy giảm hiệu suất Firebird đáng chú ý. Tuy nhiên, để đảm bảo hiệu suất cao của hệ thống với số lượng kết nối lớn, đặc biệt trên Classic và SuperClassic, ý tưởng tốt là dành riêng 30% RAM cho bộ nhớ đệm tệp.
8. Sử dụng irqbalance trên Linux
irqbalance thường cải thiện hiệu suất Firebird và cân bằng tải CPU trên các máy chủ có số lượng lõi cao.
9. Đối với Máy ảo - cẩn thận Memory Overcommit
Máy ảo có thể được cấu hình để có nhiều bộ nhớ hơn so với bộ nhớ vật lý tồn tại trên máy chủ - với tính năng được gọi là Memory Overcommit (tên có thể khác nhau trên các hệ thống ảo hóa khác nhau). Điều đó có nghĩa là trong trường hợp đỉnh điểm tiêu thụ bộ nhớ (trên VM có máy chủ cơ sở dữ liệu hoặc trên VM lân cận), swap có thể bắt đầu, dẫn đến độ trễ đáng kể. Đối với VM hiệu suất cao dành cho máy chủ cơ sở dữ liệu, tất cả bộ nhớ nên được cấp phát tĩnh.
10. Đối với Máy ảo - kiểm tra giới hạn VM
Thường thì các VM được tạo với giới hạn CPU và IO mặc định, có thể rất thấp, như 50 IOPS và 10% CPU. Kiểm tra cài đặt VM máy chủ của bạn và loại bỏ mọi giới hạn - máy chủ cơ sở dữ liệu hiệu suất cao nên có tất cả CPU, băng thông và IO khả dụng.
11. Dọn dẹp các tệp tạm thời của Firebird
Firebird tạo nhiều tệp tạm thời cho các hoạt động khác nhau: sắp xếp, xử lý BLOB, tracing. Các tệp này được lưu trữ tại các vị trí sau: trên Windows C:\ProgramData\firebird, trên Linux / tmp / firebird
Thông thường các tệp này nên được tự động dọn dẹp, tuy nhiên, đôi khi điều đó không xảy ra (ví dụ, trong trường hợp khởi động lại máy chủ).
Kiểm tra các thư mục này định kỳ và dọn dẹp các tệp cũ - có thể có nhiều GB các tệp lỗi thời fb_NNN, và việc dọn dẹp chúng sẽ giải phóng không gian trên ổ hệ thống.
12. Đừng quên bật bộ nhớ đệm tệp với bộ nhớ đệm Firebird lớn
Như bạn đã biết, bộ nhớ đệm Firebird (còn gọi là «page buffers») được chỉ định bởi tham số DefaultDBCachePages trong firebird.conf/databases.conf, hoặc trực tiếp trong header của cơ sở dữ liệu.
Trong Firebird 3 SuperServer, kích thước của bộ nhớ đệm này có thể được đặt rất cao, nhưng điều quan trọng là phải nhớ về một tham số khác: FileSystemCacheThreshold.
Nếu FileSystemCacheThreshold nhỏ hơn DefaultDBCachePages hoặc page buffers, bộ nhớ đệm tệp của hệ điều hành sẽ không được sử dụng, điều này có thể dẫn đến các vấn đề về hiệu suất.
Trong 99% trường hợp, tốt hơn là nên bật bộ nhớ đệm tệp.
Để đảm bảo điều này, luôn đặt các tham số theo quy tắc sau:
- DefaultDBCachePages = X
- FileSystemCacheThreshold = X+ N, N>1
Có những trường hợp hiếm khi tắt bộ nhớ đệm tệp cải thiện hiệu suất - nếu bạn có ví dụ như vậy, xin vui lòng liên hệ với tôi - [email protected]!
13. Tăng tốc cơ sở dữ liệu bảo mật
Mỗi kết nối đến cơ sở dữ liệu Firebird thiết lập kết nối đến cơ sở dữ liệu bảo mật (security3.fdb trong trường hợp Firebird 3), và thực hiện một số thao tác đọc và ghi (trang giao dịch, trang header). Nếu bạn có các kết nối thường xuyên, hiệu suất của cơ sở dữ liệu bảo mật của bạn có thể trở thành vấn đề.
Tối thiểu, bạn có thể làm như sau:
- Tăng page buffers cho securityN.fdb (tối ưu theo kinh nghiệm là 256 buffers)
- Di chuyển security3.fdb sang ổ đĩa nhanh (đây là tính năng tiêu chuẩn trong Firebird 3, trong 2.5 sẽ yêu cầu cài đặt lại)
Sau đó, bạn có thể đặt Forced Writes OFF cho cơ sở dữ liệu bảo mật - rủi ro nhỏ về hỏng hóc không phải là vấn đề trong trường hợp này.
Cách triệt để nhất là làm cho cơ sở dữ liệu bảo mật ở chế độ chỉ đọc - điều này sẽ loại bỏ tất cả các thao tác ghi vào nó.
Nếu bạn không thường xuyên thay đổi người dùng trong cơ sở dữ liệu bảo mật, đây là giải pháp tốt nhất.
14. Thử SuperClassic trên Firebird 3
Trong Firebird 3, kiến trúc SuperServer được quảng cáo rầm rộ như giải pháp hiệu suất tối ưu, nhưng có một số loại tải cho thấy hiệu suất tốt hơn với SuperClassic (nhưng không phải Classic - nó luôn hoạt động chậm hơn SuperServer/SuperClassic).
Làm thế nào để thực hiện thử nghiệm này một cách an toàn? Làm theo các bước dưới đây:
Để thử SuperClassic
- Đặt trong firebird.conf
- ServerMode=SuperClassic
- DefaultDbCachePages=1024
- gfix -buff 0
- Khởi động lại Firebird
Để quay lại SuperServer
- Đặt trong firebird.conf
- ServerMode=SuperServer
- DefaultDbCachePages=N # N*page size*databases_count < 25% RAM
- FileSystemCacheThreshold = N+1
- gfix -buff 0
- Khởi động lại Firebird
Xin vui lòng viết cho tôi ([email protected]) về kết quả của thử nghiệm, tôi rất quan tâm để xem kết quả.
15. Cơ sở dữ liệu lớn? Tăng kích thước trang
Theo mặc định, các cơ sở dữ liệu Firebird có các kích thước trang sau:
- 2.5 - 4096 byte
- 3.0 - 8192 byte
Tuy nhiên, kích thước trang tối đa là 16K (trong 4.0 - 32K).
Đối với các cơ sở dữ liệu lớn hơn 100Gb, trong 95% trường hợp, tốt hơn là sử dụng kích thước trang lớn nhất có sẵn, để:
- Giảm độ sâu của chỉ mục. Nên có các chỉ mục với độ sâu nhỏ hơn hoặc bằng 3. Các chỉ mục có độ sâu 4 và 5 sẽ chậm hơn nhiều
- Tăng khả năng sử dụng RAM. Bộ nhớ đệm Firebird được chỉ định theo trang, 1000 trang với kích thước trang 8K sẽ là 8Mb bộ nhớ thực tế, và với 16K - 16Mb.
- Giảm số lượng trang hệ thống. Điều này sẽ tăng tốc độ truy cập vào các bản ghi của các bảng lớn (ít bước nhảy con trỏ-con trỏ-trang dữ liệu hơn), và giúp ích cho việc chuẩn bị các truy vấn SQL lớn. Để tăng kích thước trang của cơ sở dữ liệu, cơ sở dữ liệu nên được sao lưu bằng công cụ gbak và sau đó khôi phục với tham số -page ( gbak -c -page 16384).
Xin lưu ý: nếu bạn có cơ sở dữ liệu với nhiều blob nhỏ, việc tăng kích thước trang có thể giảm phân mảnh hoặc tăng phân mảnh, và rất khó để dự đoán liệu nó sẽ tăng hay giảm hiệu suất.
16. Không sử dụng cờ no_reserve
Cờ no_reserve làm cho Firebird không dành riêng không gian trống (30%) trên các trang dữ liệu cho các phiên bản bản ghi có thể xảy ra sau UPDATE hoặc DELETE. Cờ này cho phép dữ liệu được lưu trữ một cách gọn gàng hơn (và kích thước cơ sở dữ liệu cũng nhỏ hơn), nhưng trong trường hợp UPDATE/DELETE, tất cả các thay đổi sẽ chuyển đến trang dữ liệu mới. Kết quả là, trong cơ sở dữ liệu có cờ no_reserve, các hoạt động UPDATE/DELETE chậm hơn.
Vì vậy, nếu cơ sở dữ liệu của bạn không phải là chỉ đọc, tôi khuyên bạn nên loại bỏ cờ no_reserve.
Cách kiểm tra xem nó đã được đặt hay chưa - xem dòng Attributes trong đầu ra của
gstat -h database
Cách vô hiệu hóa:
gfix -use reserve database
Sau lệnh này, các trang dữ liệu mới sẽ được tạo với không gian dành riêng.
Tuy nhiên, để đạt được hiệu quả đầy đủ, cần phải sao lưu cơ sở dữ liệu bằng gbak và sau đó khôi phục, trong trường hợp này, tất cả các trang dữ liệu sẽ có không gian dành riêng.
Xin lưu ý: kích thước cơ sở dữ liệu sẽ tăng sau khi loại bỏ cờ no_reserve và sao lưu/khôi phục.
17. Đặt kích thước ban đầu cao cho bảng khóa Firebird
Bảng khóa là cơ chế của Firebird, được sử dụng để đồng bộ hóa quyền truy cập vào các đối tượng nội bộ của engine.
Bảng khóa Firebird có thể tự động tăng kích thước, nhưng việc tăng này là một thao tác chậm, có thể dẫn đến hiện tượng đơ nhẹ. Bảng khóa chỉ có thể tăng, bắt đầu từ kích thước ban đầu (được thiết lập trong firebird.conf).
Để tránh nhiều lần tăng bảng khóa, một ý tưởng hay là theo dõi kích thước của bảng khóa vào cuối kỳ làm việc (ngày, tuần, v.v.), sau đó đặt nó làm kích thước ban đầu trong firebird.conf.
LockMemSize=99999999
Để bạn tham khảo: LockMemSize trên các hệ thống tải cao với ~1000 người dùng thường dưới 200Mb.
18. Sử dụng fb_lock_print để đếm số kết nối đến cơ sở dữ liệu
Lấy số lượng kết nối cơ sở dữ liệu là một tác vụ thường gặp đối với các nhà phát triển cơ sở dữ liệu: ví dụ, nó có thể cần thiết cho mục đích cấp phép.
Các nhà phát triển thường sử dụng truy vấn SELECT count(*) FROM MON$ATTACHMENTS để lấy giá trị này, nhưng đây không phải là cách tối ưu: các truy vấn thường xuyên đến các bảng MON$ có thể là gánh nặng cho cơ sở dữ liệu, vì vậy tốt hơn nên sử dụng phương án thay thế:
Chạy
fb_lock_print -d tên_cơ_sở_dữ_liệu | alias
và kiểm tra giá trị Owners - nó sẽ hiển thị số kết nối hiện tại đến cơ sở dữ liệu.
19. Tránh các LEFT JOIN không cần thiết
Tôi thường thấy các truy vấn với cấu trúc như thế này:
T1 LEFT JOIN T2 ON (…) WHERE T2.Field_condition
Về cơ bản, điều kiện trên T2 loại bỏ các giá trị NULL khỏi kết quả của LEFT JOIN T2, vì vậy có thể đổi LEFT JOIN thành INNER JOIN - điều này sẽ không ảnh hưởng đến kết quả của truy vấn.
INNER JOIN mang lại nhiều tự do hơn cho bộ tối ưu hóa của Firebird, và trong các phiên bản hiện đại của Firebird, nó được tối ưu hóa tốt hơn nhiều so với LEFT.
Đặc biệt, điều này có ý nghĩa trong các trường hợp sau:
- Không có điều kiện cho T1 trong mệnh đề WHERE
- T2 là một bảng nhỏ
20. Tránh đếm bản ghi không cần thiết
Một lỗi phổ biến khác trong các truy vấn cơ sở dữ liệu phức tạp và các thủ tục lưu trữ là sử dụng select count() chỉ để kiểm tra sự tồn tại của bản ghi.
Truy vấn sau sẽ đọc tất cả các bản ghi theo condition1:
(select count(*)…. where condition11) >0
Tốt hơn nên sử dụng cấu trúc này thay thế
Exists(select first 1 id where condition1)
Nếu condition1 trả về nhiều hơn 1 bản ghi, phương án đề xuất sẽ nhanh hơn nhiều, vì nó không đọc tất cả các bản ghi, nó dừng lại sau bản ghi đầu tiên được lấy.
21. Tránh sắp xếp không cần thiết trong các thủ tục lưu trữ
Việc sắp xếp kết quả của truy vấn bên trong thủ tục lưu trữ nên được biện minh bởi logic nghiệp vụ.
Ví dụ, trong thủ tục lưu trữ dưới đây, mệnh đề ORDER BY là vô dụng từ quan điểm logic nghiệp vụ, nhưng nó thêm một thao tác sắp xếp không cần thiết.
create or alter procedure NEW_PROCEDURE
returns (
SUMX double precision)
as
declare variable _amount double precision;
begin
for select T1.amount from Table1 t1 where ....
order by id
into :_amount
do
begin
sumx=sumx+_amount
end;
suspend;
end
Hãy kiểm tra mã PSQL của bạn để tìm các tình huống tương tự và loại bỏ ORDER BY vô dụng (cũng như distinct và UNION).
22. Không giữ các truy vấn ở trạng thái prepared khi không cần thiết
Chúng tôi thường thấy 500-1000 câu lệnh prepared trong mỗi kết nối (có thể kiểm tra bằng các truy vấn MON$).
Phần lớn trong số chúng chỉ chạy một lần, sau đó chúng chỉ nằm trong RAM, làm cho working set của Firebird lớn hơn và làm chậm các truy vấn MON$.
Khuyến nghị là chỉ giữ các truy vấn SQL ở trạng thái prepared khi chúng được dự định chạy nhiều lần, hoặc nếu thời gian prepare của chúng lớn (có thể xảy ra với các truy vấn rất lớn có nhiều join và truy cập vào các bảng khổng lồ).
23. Luôn đóng các truy vấn có sắp xếp lớn
Cho đến khi truy vấn SQL có sắp xếp (ORDER BY, GROUP BY, UNION, distinct) chưa được đóng, Firebird vẫn giữ các bản ghi đã sắp xếp trong bộ nhớ. Kích thước bộ nhớ được phân bổ cho việc sắp xếp được thiết lập bởi tham số TempCacheLimit trong firebird.conf, mặc định là 64Mb.
Ngay cả khi tăng TempCacheLimit, các truy vấn chạy lâu với số lượng lớn bản ghi được sắp xếp cuối cùng sẽ tiêu thụ hết lượng được phân bổ, và kết quả là việc sắp xếp sẽ chuyển sang các tệp tạm thời (tức là đĩa). Kết quả là, điều này có thể dẫn đến chậm đáng kể.
Khuyến nghị là đóng tất cả các truy vấn như vậy một cách kịp thời.
Có câu hỏi nào không?
Vui lòng liên hệ với tôi nếu có bất kỳ câu hỏi nào: [email protected]!