Firebird 속도를 높이는 23가지 추가 방법
Alexey Kovyazin, IBSurgeon, [email protected], 2019년 1월 8일
번역: 포르투갈어
“23개 더"란?
여러분 중 일부는 2016년 5월에 게시된 «Firebird 속도를 높이는 45가지 방법» 기사를 기억하실 것입니다. 이제 대부분 Firebird 데이터베이스와 다수의 연결(1000개 이상)을 가진 서버의 최적화 및 유지 관리 경험을 바탕으로 한 다음 팁과 요령 시리즈를 게시할 때입니다.
1. Windows Server 2016 및 2019에서 전원 옵션을 고성능으로 설정
기본적으로 Windows Server의 전원 계획은 “균형 조정"으로 설정되어 있으며, 이는 데이터베이스 서버에 적합하지 않습니다. 이를 “고성능"으로 설정하면 CPU 집약적 작업에서 약 +20%의 성능 향상을 얻을 수 있습니다. 재시작이나 재부팅 없이 온라인으로 설정할 수 있습니다. 아래 그림은 “고성능” 전원 계획의 이점을 보여주는 CPU 그래프입니다:

Windows 전원 계획에 대한 테스트 세부 정보는 여기에서 확인할 수 있습니다.
2. Windows의 Classic에서 «데스크톱과 상호 작용» 활성화
Windows에서 Classic 아키텍처로 Firebird를 사용하는 경우 «서비스가 데스크톱과 상호 작용하도록 허용» 확인란을 활성화하십시오. 이 설정이 없으면 “데스크톱 힙” 리소스가 Windows에 의해 제한되어 Firebird가 250-300개 이상의 연결을 열 수 없습니다(데이터베이스의 메타데이터 및 관련 메모리 소비에 따라 다름) - 메모리 부족 오류가 발생합니다.

3. 주의: 도메인 컨트롤러
도메인 컨트롤러 역할을 하는 Windows가 Active Directory 데이터베이스가 있는 디스크의 쓰기 캐시를 비활성화하는 문제입니다.
이는 Firebird에 다양한 방식으로 영향을 미치며(물론 다른 애플리케이션에도 마찬가지), Active Directory 역할이 없는 서버보다 현저히 나쁜 성능을 보입니다.
이 문제는 Windows Small Business Server 2011과 같은 인기 있는 Windows 버전 및 DC가 있는 다른 버전에도 영향을 미친다는 점에 유의하십시오.
4. Linux에서 «최대 열린 파일» 제한 늘리기
Linux를 데이터베이스 서버로 사용하는 경우 Firebird의 제한 조정을 잊지 마십시오. 다음 명령으로 Firebird 프로세스(SuperServer 또는 SuperClassic)의 제한을 확인하십시오:
cat /proc//limits
그리고 최대 열린 파일 수가 있는 줄에 주의하십시오.
Firebird는 연결당 최대 4개의 핸들을 사용할 수 있으며, 다음과 같은 경우:
Max open files 4096 4096 files
이는 Firebird 프로세스가 처리하는 총 연결 수가 약 1000개로 제한된다는 것을 의미합니다.
참고 - 서버에 4개의 데이터베이스가 있는 경우 각 데이터베이스에 대한 연결이 계산됩니다.
더 많이 설정하십시오 - 65535를 권장합니다.
Firebird 프로세스를 재시작한 후 다시 확인하는 것을 잊지 마십시오: 적용되었는지 여부.
Classic 아키텍처의 경우 «firebird» 사용자에 대한 제한을 확인하고 늘려야 합니다.
5. 최신 Linux 사용
예, 이 조언이 사소하다는 것을 이해하지만, CentOS 6에서 7로, Ubuntu 12에서 16으로 마이그레이션한 후(동일한 하드웨어에서!) 상당한 성능 향상을 여러 번 보았으므로 이제 250-300개 이상의 연결을 가진 데이터베이스 서버에 대한 필수 권장 사항입니다. 최신 Linux는 추가 최적화 단계 전제 조건입니다.
권장 Linux 버전: CentOS 7.x 및 Ubuntu 16, 18.
6. Windows에서 파일 캐시를 위해 RAM의 40% 예약
OS 메모리 관리자는 메모리 할당과 관련하여 영향을 미치며, 기본적으로 Windows는 파일 캐시를 위해 RAM의 40%를 요구합니다.
불행히도 빈약한 도구인 Windows 작업 관리자는 파일 캐시에 사용되는 메모리를 «사용 가능»으로 표시하며, 일부 관리자는 Firebird가 이 모든 사용 가능한 메모리를 소비하도록 하려고 firebird.conf의 DefaultDBCachePage 매개변수를 매우 높은 값으로 설정하여 일반적으로 스와핑을 초래합니다.
Windows에서 실제 메모리 사용량을 확인하려면 항상 RAMMap 도구를 사용하십시오.
Firebird 서버로 사용하도록 전용된 Windows Server에 대한 경험적 규칙은 다음과 같습니다: Firebird 메모리(작업 집합)는 총 RAM의 40% 미만이어야 합니다. 모든 프로세스의 작업 집합 총 크기가 50% 이상이면 Windows에서 스왑이 시작될 수 있습니다.
참고: 여기서 “예약"은 “Firebird에서 너무 많은 페이지 버퍼를 설정하지 마십시오"뿐만 아니라 다른 소프트웨어의 메모리 사용을 제한하는 것도 중요합니다. 예를 들어, Firebird와 동일한 서버에 MS Exchange 또는 MSSQL이 있는 경우 해당 메모리 요구를 제한하십시오.
세부 정보를 알고 싶으시면 Firebird의 메모리 관리에 관한 웹 세미나를 녹화했습니다:
7. Linux에서 파일 캐시를 위해 RAM의 30% 예약
Linux는 Windows와 다른 방식으로 파일 캐시와 작동하며, 일반적으로 파일 캐시에 사용되는 RAM의 양은 눈에 띄는 Firebird 성능 저하 없이 Windows보다 상당히 적을 수 있습니다. 그러나 특히 Classic 및 SuperClassic에서 많은 연결을 가진 시스템의 높은 성능을 보장하려면 파일 캐시를 위해 RAM의 30%를 예약하는 것이 좋습니다.
8. Linux에서 irqbalance 사용
irqblalnce는 종종 Firebird 성능과 많은 코어를 가진 서버의 CPU 부하 분산을 개선합니다.
9. 가상 머신의 경우 - 메모리 오버커밋 주의
가상 머신은 메모리 오버커밋(다른 가상화 시스템에서는 이름이 다를 수 있음)이라는 기능을 통해 호스트 머신에 물리적으로 존재하는 것보다 더 많은 메모리를 갖도록 구성할 수 있습니다. 이는 메모리 소비가 최고조에 달할 경우(데이터베이스 서버가 있는 VM 또는 이웃 VM에서) 스왑이 시작되어 상당한 지연을 초래할 수 있음을 의미합니다. 데이터베이스 서버용으로 의도된 고성능 VM의 경우 모든 메모리는 정적이어야 합니다.
10. 가상 머신의 경우 - VM 제한 확인
종종 VM은 기본 CPU 및 IO 제한으로 생성되며, 50 IOPS 및 10% CPU와 같이 매우 낮을 수 있습니다. 서버 VM 설정을 확인하고 모든 제한을 제거하십시오 - 고성능 데이터베이스 서버는 가능한 모든 CPU, 대역폭 및 IO를 가져야 합니다.
11. Firebird 임시 파일 정리
Firebird는 정렬, BLOB 처리, 추적 등 다양한 작업을 위해 많은 임시 파일을 생성합니다. 이 파일들은 다음 위치에 저장됩니다: Windows에서는 C:\ProgramData\firebird, Linux에서는 / tmp / firebird
일반적으로 이 파일들은 자동으로 정리되어야 하지만 때로는 그렇지 않습니다(예: 서버 재부팅의 경우).
이 폴더를 주기적으로 확인하고 오래된 파일을 정리하십시오 - 오래된 fb_NNN 파일이 수 GB에 달할 수 있으며, 이를 정리하면 시스템 드라이브의 공간이 확보됩니다.
12. 큰 Firebird 캐시로 파일 캐시를 활성화하는 것을 잊지 마십시오
아시다시피, Firebird 캐시(«페이지 버퍼»라고도 함)는 firebird.conf/databases.conf의 DefaultDBCachePages 매개변수 또는 데이터베이스 헤더에서 직접 지정됩니다.
Firebird 3 SuperServer에서 이 캐시의 크기는 매우 높게 설정할 수 있지만, 다른 매개변수인 FileSystemCacheThreshold를 기억하는 것이 중요합니다.
FileSystemCacheThreshold가 DefaultDBCachePages 또는 페이지 버퍼보다 작으면 운영 체제의 파일 캐시가 사용되지 않아 성능 문제가 발생할 수 있습니다.
99%의 경우 파일 캐시를 활성화하는 것이 좋습니다.
이를 보장하려면 항상 다음 규칙에 따라 매개변수를 설정하십시오:
- DefaultDBCachePages = X
- FileSystemCacheThreshold = X+ N, N>1
파일 캐시를 비활성화하면 성능이 향상되는 드문 경우가 있습니다 - 그러한 예가 있으면 저에게 연락하십시오 - [email protected]!
13. 보안 데이터베이스 속도 향상
Firebird 데이터베이스에 대한 모든 연결은 보안 데이터베이스(Firebird 3의 경우 security3.fdb)에 대한 연결을 설정하고 여러 읽기 및 쓰기(트랜잭션 페이지, 헤더 페이지)를 수행합니다. 연결이 빈번한 경우 보안 데이터베이스의 성능이 문제가 될 수 있습니다.
최소한 다음을 수행할 수 있습니다:
- securityN.fdb의 페이지 버퍼를 늘리십시오 (경험적 최적값은 256 버퍼입니다)
- security3.fdb를 빠른 드라이브로 옮기십시오 (Firebird 3에서는 표준 기능이며, 2.5에서는 재설치가 필요합니다)
그런 다음, 보안 데이터베이스에 대해 Forced Writes를 OFF로 설정할 수 있습니다. 이 경우 손상될 가능성이 적은 것은 문제가 되지 않습니다.
가장 극단적인 방법은 보안 데이터베이스를 읽기 전용으로 만드는 것입니다. 그러면 해당 데이터베이스에 대한 모든 쓰기가 제거됩니다.
보안 데이터베이스에서 사용자를 자주 변경하지 않는다면, 이것이 최선의 해결책입니다.
14. Firebird 3에서 SuperClassic 사용해 보기
Firebird 3에서 SuperServer 아키텍처는 궁극의 성능 솔루션으로 크게 홍보되었지만, SuperClassic에서 더 나은 성능을 보이는 부하 유형도 있습니다 (Classic은 아닙니다. Classic은 항상 SuperServer/SuperClassic보다 느리게 작동합니다).
안전한 방법으로 이 실험을 수행하는 방법은 무엇일까요? 아래 단계를 따르십시오:
SuperClassic을 사용해 보려면
- firebird.conf에서 설정
- ServerMode=SuperClassic
- DefaultDbCachePages=1024
- gfix -buff 0
- Firebird 재시작
SuperServer로 되돌리려면
- firebird.conf에서 설정
- ServerMode=SuperServer
- DefaultDbCachePages=N # N*페이지 크기*데이터베이스_수 < RAM의 25%
- FileSystemCacheThreshold = N+1
- gfix -buff 0
- Firebird 재시작
실험 결과에 대해 저([email protected])에게 알려주십시오. 결과를 보고 싶습니다.
15. 큰 데이터베이스인가요? 페이지 크기를 늘리십시오
기본적으로 Firebird 데이터베이스의 페이지 크기는 다음과 같습니다:
- 2.5 - 4096 바이트
- 3.0 - 8192 바이트
그러나 최대 페이지 크기는 16K입니다 (4.0에서는 32K).
100Gb가 넘는 데이터베이스의 경우 95%의 사례에서 다음을 위해 사용 가능한 가장 큰 페이지 크기를 사용하는 것이 좋습니다:
- 인덱스의 깊이 감소. 깊이가 3 이하인 인덱스를 사용하는 것이 권장됩니다. 깊이가 4와 5인 인덱스는 훨씬 느려집니다
- RAM 활용도 증가. Firebird 캐시는 페이지 단위로 지정되며, 8K 페이지 크기로 1000 페이지는 실제 메모리 8Mb이고, 16K로는 16Mb입니다.
- 시스템 페이지 수 감소. 이는 큰 테이블의 레코드에 대한 접근 속도를 높이고(포인터-포인터-데이터 페이지로의 점프 감소), 큰 SQL 쿼리 준비에 도움이 됩니다. 데이터베이스의 페이지 크기를 늘리려면 gbak 도구로 데이터베이스를 백업한 다음 -page 매개변수로 복원해야 합니다 ( gbak -c -page 16384).
참고: 작은 블롭이 많은 데이터베이스의 경우 페이지 크기를 늘리면 단편화가 감소하거나 증가할 수 있으며, 성능이 증가할지 감소할지 예측하기 어렵습니다.
16. no_reserve 플래그를 사용하지 마십시오
no_reserve 플래그는 Firebird가 UPDATE 또는 DELETE 후에 발생하는 가능한 레코드 버전을 위해 데이터 페이지에 여유 공간(30%)을 예약하지 않도록 합니다. 이 플래그를 사용하면 데이터를 더 압축된 방식으로 저장할 수 있으며(데이터베이스 크기도 더 작아짐), 그러나 UPDATE/DELETE의 경우 모든 변경 사항이 새 데이터 페이지로 이동합니다. 결과적으로 no_reserve 플래그가 있는 데이터베이스에서는 UPDATE/DELETE 작업이 더 느립니다.
따라서 데이터베이스가 읽기 전용이 아니라면 no_reserve 플래그를 제거할 것을 권장합니다.
설정되었는지 여부를 확인하는 방법 - 다음 출력의 Attributes 줄을 참조하십시오
gstat -h database
비활성화하는 방법:
gfix -use reserve database
이 명령 후에 새 데이터 페이지는 예약된 공간과 함께 생성됩니다.
그러나 완전한 효과를 얻으려면 gbak으로 데이터베이스를 백업한 다음 복원해야 하며, 이 경우 모든 데이터 페이지에 예약된 공간이 있게 됩니다.
참고: no_reserve 플래그를 제거하고 백업/복원 후에 데이터베이스 크기가 증가합니다.
17. Firebird 잠금 테이블의 초기 크기를 크게 설정하십시오
잠금 테이블은 내부 엔진 객체에 대한 접근을 동기화하는 데 사용되는 Firebird의 메커니즘입니다.
Firebird 잠금 테이블은 자동으로 증가할 수 있지만, 그 증가는 느린 작업이며 마이크로 프리즈를 초래할 수 있습니다. 잠금 테이블은 초기 크기(firebird.conf에 설정됨)에서 시작하여 증가만 할 수 있습니다.
잠금 테이블의 여러 차례 증가를 방지하려면, 작업 기간(일, 주 등)이 끝날 때 잠금 테이블의 크기를 관찰한 다음 firebird.conf의 초기 크기로 설정하는 것이 좋습니다.
LockMemSize=99999999
참고: 약 1000명의 사용자가 있는 고부하 시스템에서 LockMemSize는 일반적으로 200Mb 미만입니다.
18. fb_lock_print를 사용하여 데이터베이스에 대한 연결 수를 세십시오
데이터베이스 연결 수를 얻는 것은 데이터베이스 개발자에게 빈번한 작업입니다. 예를 들어 라이선스 목적으로 필요할 수 있습니다.
종종 개발자들은 이 값을 얻기 위해 SELECT count(*) FROM MON$ATTACHMENTS 쿼리를 사용하지만, 이는 최적의 방법이 아닙니다. MON$ 테이블에 대한 빈번한 쿼리는 데이터베이스에 부담이 될 수 있으므로 대안을 사용하는 것이 좋습니다:
실행
fb_lock_print -d database_name | alias
그리고 Owners 값을 확인하십시오. 현재 데이터베이스에 대한 연결 수를 보여줍니다.
19. 불필요한 LEFT JOIN을 피하십시오
종종 다음과 같은 구성의 쿼리를 봅니다:
T1 LEFT JOIN T2 ON (…) WHERE T2.Field_condition
본질적으로 T2에 대한 조건은 LEFT JOIN T2의 출력에서 NULL을 제외하므로, LEFT JOIN을 INNER JOIN으로 변경할 수 있으며 쿼리 결과에는 영향을 미치지 않습니다.
INNER JOIN은 Firebird 옵티마이저에게 더 많은 자유를 주며, 최신 버전의 Firebird에서는 LEFT보다 훨씬 더 잘 최적화됩니다.
특히 다음과 같은 경우에 의미가 있습니다:
- WHERE 절에 T1에 대한 조건이 없음
- T2가 작은 테이블임
20. 불필요한 레코드 카운팅을 피하십시오
복잡한 데이터베이스 쿼리와 저장 프로시저에서 또 다른 흔한 실수는 레코드의 존재를 확인하기 위해 select count()를 사용하는 것입니다.
다음 쿼리는 condition1에 따라 모든 레코드를 읽습니다:
(select count(*)…. where condition11) >0
대신 이 구성을 사용하는 것이 좋습니다
Exists(select first 1 id where condition1)
condition1이 1개 이상의 레코드를 반환하는 경우, 제안된 옵션이 훨씬 빠릅니다. 모든 레코드를 읽지 않고 첫 번째로 가져온 레코드 후에 중지하기 때문입니다.
21. 저장 프로시저에서 불필요한 정렬을 피하십시오
저장 프로시저 내에서 쿼리 결과의 정렬은 비즈니스 로직에 의해 정당화되어야 합니다.
예를 들어, 아래 저장 프로시저의 예에서 ORDER BY 절은 비즈니스 로직 관점에서 쓸모가 없지만, 불필요한 정렬 작업을 추가합니다.
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
PSQL 코드에서 유사한 상황을 확인하고 쓸모없는 ORDER BY(그리고 distinct 및 UNION)를 제거하십시오.
22. 필요하지 않은 경우 준비된 상태로 쿼리를 유지하지 마십시오
종종 각 연결에서 500-1000개의 준비된 문을 봅니다 (MON$ 쿼리로 확인할 수 있습니다).
그 중 대다수는 한 번만 실행되고, 그런 다음 RAM에 그대로 있어 Firebird 작업 집합을 더 크게 만들고 MON$ 쿼리를 느리게 합니다.
권장 사항은 SQL 쿼리를 여러 번 시작할 의도가 있거나 준비 시간이 긴 경우(조인이 많고 거대한 테이블에 접근하는 매우 큰 쿼리의 경우 그럴 수 있음)에만 준비된 상태로 유지하는 것입니다.
23. 큰 정렬이 있는 쿼리는 항상 닫으십시오
정렬(ORDER BY, GROUP BY, UNION, distinct)이 있는 SQL 쿼리가 닫히지 않는 한, Firebird는 정렬된 레코드를 메모리에 유지합니다. 정렬에 할당되는 메모리 크기는 firebird.conf의 TempCacheLimit 매개변수로 설정되며, 기본값은 64Mb입니다.
TempCacheLimit을 늘리더라도, 정렬된 레코드 수가 많은 장기 실행 쿼리는 결국 할당된 양을 모두 소비하게 되며, 결과적으로 정렬이 임시 파일(즉, 디스크)로 이동합니다. 결과적으로 상당한 느려짐을 초래할 수 있습니다.
권장 사항은 그러한 모든 쿼리를 적시에 닫는 것입니다.
질문이 있으신가요?
질문이 있으시면 언제든지 저에게 연락해 주십시오: [email protected]!