23 cách khác để tăng tốc Firebird
Alexey Kovyazin, IBSurgeon, [email protected], 08-Jan-2019
Bản dịch: Tiếng Bồ Đào Nha
Tại sao lại là “23 điều 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. Giờ đây đã đến 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 thành Hiệu suất cao trong Windows Server 2016 và 2019
Theo mặc định, Windows Server có kế hoạch nguồn điện được đặt thành “Balanced” (Cân bằng), không phù hợp cho máy chủ cơ sở dữ liệu. Hãy đặt thành “High Performance” (Hiệu suất cao) và đạt được khoảng +20% hiệu suất cho các hoạt động tốn nhiều CPU. Có thể đặt trực tuyến, không cần khởi động lại hoặc khởi động lại máy. Hình dưới đây cho thấy biểu đồ CPU, minh họa lợi thế của kế hoạch nguồn điện “High-performance”:

Chi tiết thêm về các thử nghiệm của chúng tôi với kế hoạch nguồn điện Windows có thể tìm thấy tại đây.
2. Bật «Interact with desktop» 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 «Allow service to interact with desktop». Không có cài đặt này, tài nguyên «desktop heap» bị Windows giới hạn, và Firebird không thể mở quá 250-300 kết nối (phụ thuộc vào siêu dữ liệu của cơ sở dữ liệu và mức tiêu thụ bộ nhớ liên quan) - sẽ xảy ra 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.
Nó ả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 trên 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ệp mở tối đa.
Firebird có thể sử dụng tối đa 4 handle cho mỗi kết nối, và nếu bạn có một cái 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.
Đặt cao 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: 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 đã nhiều lần thấy 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 phần cứng!), vì vậy giờ đây nó là khuyến nghị bắt buộc đối với 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 40% RAM cho bộ nhớ đệm tệp trên Windows
Trình quản lý bộ nhớ của hệ điều hành 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ụ Windows Task Manager kém cỏi 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 thành các giá trị rất cao, và điều này thường dẫn đến hoán đổi.
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 thực nghiệm cho Windows Server (dành riêng để sử dụng làm máy chủ Firebird) là như sau: bộ nhớ Firebird (Working Set) phải nhỏ hơn 40% tổng RAM. Nếu tổng kích thước của working set cho tất cả các tiến trình lớn hơn 50%, Windows có thể bắt đầu hoán đổi.
Xin lưu ý: “dành” ở đây không chỉ có nghĩa là “không đặt quá nhiều bộ đệm trang trong Firebird” mà còn quan trọng là hạn chế việ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 muốn biết chi tiết, tôi đã ghi lại hội thảo trực tuyến dành riêng cho 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 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 trên Windows mà không làm giảm hiệu suất Firebird đáng kể. 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 cao, đặc biệt trên Classic và SuperClassic, ý tưởng tốt là dành 30% RAM cho bộ nhớ đệm tệp.
8. Sử dụng irqbalance trên Linux
irqblalnce 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ó nhiều lõi.
9. Đối với Máy ảo - cẩn thận với Memory Overcommit
Máy ảo có thể được cấu hình để có nhiều bộ nhớ hơn so với thực tế tồn tại trên máy chủ vật lý - với một 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), hoán đổi 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ớ phải là 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 phải có tất cả CPU, băng thông và IO có thể.
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, theo dõi. Các tệp này được lưu trữ ở 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 sẽ được dọn dẹp tự động, 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 tệp fb_NNN lỗi thời, và việc dọn dẹp chúng sẽ giải phóng dung lượng trên ổ đĩa 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 được 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 phần đầu 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à 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 hoi khi vô hiệu hóa bộ nhớ đệm tệp cải thiện hiệu suất - nếu bạn có ví dụ như vậy, 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ố lần đọc và ghi (trang giao dịch, trang tiêu đề). Nếu bạn 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 thực nghiệm là 256 bộ đệm)
- 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ẽ cần cài đặt lại)
Sau đó, bạn có thể đặt Forced Writes OFF cho cơ sở dữ liệu bảo mật - khả năng nhỏ bị hỏng 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ỉ đọc - nó sẽ loại bỏ tất cả các lần 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, đó 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ư là giải pháp hiệu suất tối ưu, nhưng có một số loại tải thể hiện 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? Thực hiện 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
Vui lòng viết cho tôi ([email protected]) về kết quả của thử nghiệm, tôi rất muốn xem kết quả.
15. Cơ sở dữ liệu lớn? Tăng kích thước trang
Theo mặc định, 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ơ sở dữ liệu hơn 100Gb trong 95% trường hợp, tốt hơn là có kích thước trang cao nhất có sẵn, để:
- Giảm độ sâu của chỉ mục. Khuyến nghị có chỉ mục với độ sâu nhỏ hơn hoặc bằng 3. Chỉ mục có độ sâu 4 và 5 sẽ chậm hơn nhiều
- Tăng mức sử dụng RAM. Bộ nhớ đệm Firebird được chỉ định bằng số 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. Nó sẽ tăng tốc độ truy cập vào các bản ghi của các bảng lớn (ít nhảy con trỏ-con trỏ-trang dữ liệu hơn), và giúp 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 phải đượ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 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ữ theo cách nhỏ gọn 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 đều đi đế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 xóa 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 lên sau khi xóa 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 của Firebird có thể tự động tăng trưởng, nhưng việc tăng kích thước là một thao tác chậm, có thể dẫn đến hiện tượng đóng băng vi mô. Bảng khóa chỉ có thể tăng trưởng, bắt đầu từ kích thước ban đầu (được đặt trong firebird.conf).
Để tránh nhiều vòng tăng kích thước bảng khóa, một ý tưởng tốt là theo dõi kích thước của bảng khóa vào cuối giai đoạn làm việc (ngày, tuần, v.v.), rồi đặt nó làm kích thước ban đầu trong firebird.conf.
LockMemSize=99999999
Để 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ố lượng kết nối đến cơ sở dữ liệu
Việc lấy số lượng kết nối đến cơ sở dữ liệu là một công việc 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.
Thường thì các nhà phát triển sử dụng truy vấn SELECT count(*) FROM MON$ATTACHMENTS để lấy giá trị này, nhưng đó 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 hãy sử dụng giải pháp thay thế:
Chạy
fb_lock_print -d database_name | alias
và kiểm tra giá trị Owners - nó sẽ hiển thị số lượng 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ề bản chất, điều kiện trên T2 loại trừ các NULL khỏi kết quả của LEFT JOIN T2, vì vậy có thể thay đổi LEFT JOIN thành INNER JOIN - nó sẽ không ảnh hưởng đến kết quả của truy vấn.
INNER JOIN cho bộ tối ưu hóa của Firebird nhiều tự do hơn, 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.
Điều này đặc biệt 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 việc đế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 hãy 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, tùy chọn được đề 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 việc 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ữ phải được biện minh bởi logic nghiệp vụ.
Ví dụ, trong ví dụ về thủ tục lưu trữ dưới đây, mệnh đề ORDER BY là vô ích từ quan điểm logic nghiệp vụ, nhưng nó lại 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 cho các tình huống tương tự và loại bỏ ORDER BY vô ích (cũng như distinct và UNION).
22. Không giữ các truy vấn ở trạng thái chuẩn bị khi không cần thiết
Thường thì chúng ta thấy 500-1000 câu lệnh đã chuẩn bị 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, rồi sau đó chúng chỉ nằm trong RAM, làm cho tập làm việc 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 chuẩn bị khi chúng được dự định khởi chạy nhiều lần, hoặc nếu thời gian chuẩn bị của chúng lớn (có thể như vậy đối với các truy vấn rất lớn với nhiều phép 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 cấp phát cho việc sắp xếp được đặt bởi tham số TempCacheLimit trong firebird.conf, mặc định là 64Mb.
Ngay cả với TempCacheLimit được tăng lên, các truy vấn chạy lâu với số lượng lớn các bản ghi được sắp xếp cuối cùng sẽ tiêu thụ hết toàn bộ lượng được cấp phát, 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à, nó có thể dẫn đến sự chậm chạp đá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âu hỏi?
Xin vui lòng liên hệ với tôi nếu có bất kỳ câu hỏi nào: [email protected]!