Firebird 속도를 높이는 23가지 추가 방법
Alexey Kovyazin, IBSurgeon, [email protected], 2019년 1월 8일
번역: 포르투갈어
왜 “23가지 더"인가?
여러분 중 일부는 2016년 5월에 게시된 « Firebird 속도를 높이는 45가지 방법» 기사를 기억하실 것입니다. 이제 다음 팁과 요령 시리즈를 게시할 때가 되었습니다. 이번 시리즈는 주로 높은 연결 수(1000개 이상)를 가진 Firebird 데이터베이스 및 서버의 최적화와 유지 관리 경험을 기반으로 합니다.
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 도구를 사용하십시오.
Windows Server(Firebird 서버 전용)에 대한 경험적 규칙은 다음과 같습니다: 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 사용
irqbalance는 코어 수가 많은 서버에서 Firebird 성능과 CPU 부하 분산을 개선하는 경우가 많습니다.
9. 가상 머신의 경우 - 메모리 오버커밋 주의
가상 머신은 호스트 머신에 물리적으로 존재하는 것보다 더 많은 메모리를 갖도록 구성할 수 있습니다 - 메모리 오버커밋(가상화 시스템에 따라 이름이 다를 수 있음)이라는 기능을 통해 가능합니다. 이는 메모리 소비가 최고조에 달할 때(데이터베이스 서버가 있는 VM 또는 인접 VM에서) 스왑이 시작되어 상당한 지연이 발생할 수 있음을 의미합니다. 데이터베이스 서버용 고성능 VM의 경우 모든 메모리는 정적이어야 합니다.
10. 가상 머신의 경우 - VM 제한 확인
종종 VM은 50 IOPS 및 10% CPU와 같은 매우 낮은 기본 CPU 및 IO 제한으로 생성됩니다. 서버 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은 아님 - 항상 SuperServer/SuperClassic보다 느리게 작동합니다).
이 실험을 안전하게 수행하는 방법은 무엇입니까? 아래 단계를 따르십시오:
SuperClassic을 시도하려면
- firebird.conf에서 설정
- ServerMode=SuperClassic
- DefaultDbCachePages=1024
- gfix -buff 0
- Firebird 재시작
SuperServer로 되돌리려면
- firebird.conf에서 설정
- ServerMode=SuperServer
- DefaultDbCachePages=N # N*페이지 크기*데이터베이스_수 < 25% RAM
- 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).
참고: 작은 blob이 많은 데이터베이스가 있는 경우 페이지 크기를 늘리면 조각화가 줄어들거나 늘어날 수 있으며, 성능이 향상될지 저하될지 예측하기 어렵습니다.
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이 둘 이상의 레코드를 반환하는 경우 제안된 옵션이 훨씬 빠릅니다. 모든 레코드를 읽지 않고 첫 번째 레코드를 가져온 후 중지하기 때문입니다.
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$ 쿼리를 느리게 합니다.
권장 사항은 여러 번 실행할 의도가 있거나 준비 시간이 긴 쿼리(많은 조인과 대용량 테이블 액세스가 있는 매우 큰 쿼리일 수 있음)만 준비된 상태로 유지하는 것입니다.
23. 대규모 정렬이 있는 쿼리는 항상 닫기
정렬(ORDER BY, GROUP BY, UNION, distinct)이 있는 SQL 쿼리가 닫히지 않을 때까지 Firebird는 정렬된 레코드를 메모리에 유지합니다. 정렬에 할당된 메모리 크기는 firebird.conf의 TempCacheLimit 매개변수로 설정되며 기본값은 64Mb입니다.
TempCacheLimit을 늘려도 많은 수의 정렬된 레코드가 있는 장기 실행 쿼리는 결국 할당된 모든 양을 소비하게 되며 결과적으로 정렬이 임시 파일(즉, 디스크)로 이동합니다. 결과적으로 상당한 속도 저하가 발생할 수 있습니다.
권장 사항은 이러한 모든 쿼리를 적시에 닫는 것입니다.
질문이 있으십니까?
언제든지 저에게 연락해 주십시오: [email protected]!