이 기사에서는 Rails에서 데이터베이스 성능을 테스트하는 방법과 가장 일반적인 데이터베이스 성능 문제를 해결하는 방법에 대해 설명합니다.
Rails 애플리케이션을 개발할 때 ActiveRecord는 데이터베이스를 관리하는 기본 도구입니다. ActiveRecord는 .where와 같은 명령을 사용하여 데이터를 쿼리하고 삽입할 수 있는 쉽고 빠른 인터페이스를 제공합니다. , .save , .create 및 .update . Rails는 이러한 명령을 SQL 쿼리로 변환하는 작업을 수행합니다. 이는 좋은 일이지만 때로는 성능 문제를 일으킬 수 있습니다. 몇 가지 일반적인 문제와 성능 최적화 방법을 이해하는 것이 중요합니다.
Ruby on Rails의 ActiveRecord에 대한 빠른 참고 사항
Rails ActiveRecord는 데이터베이스를 비즈니스 객체로 표시하여 관리하는 MVC(Model-View-Controller)의 계층입니다. ActiveRecord 패턴은 ORM 기술을 사용하여 애플리케이션의 개체를 관계형 데이터베이스 테이블 관리 시스템에 연결합니다.
자, 시작해 보세요!
Rails에서 데이터베이스 성능 문제를 식별하고 테스트하는 3가지 방법
1. ActiveRecord 쿼리에 대해 설명 실행
explain 문은 SQL 쿼리의 실행 계획에 대한 정보(스캔할 행 수, 사용할 인덱스, 테이블 조인 방법 등 쿼리 실행 방법)를 표시합니다.
실행 계획은 다음을 살펴봄으로써 쿼리 실행 속도를 저하시키는 요소를 파악하는 데 도움이 됩니다.
- 쿼리 성능을 향상시키기 위해 추가해야 하는 색인
- 테이블이 최적의 순서로 조인된 경우.
STRAIGHT_JOIN를 사용할 수 있습니다. 더 나은 성능을 위해 조인 문에서 테이블 순서를 강제로 적용합니다.
explain은 SELECT, DELETE, INSERT, REPLACE 및 UPDATE 문에서도 작동합니다.
ActiveRecord와 함께 explain을 사용하는 것은 매우 간단합니다. 다음을 입력하세요:
.explain 추가 명령 끝에는 ActiveRecord 명령에 대한 쿼리 계획이 제공됩니다. 위의 예는 id를 사용하는 매우 간단한 쿼리입니다. (기본 키)를 사용하여 테이블을 쿼리합니다. explain의 출력 명령문은 pkey를 사용하고 있음을 보여줍니다. . 이를 통해 해당 명령문이 최적이고 빠르다는 것을 확인할 수 있습니다.
.explain를 추가해 보세요. 사용된 인덱스와 함께 실행 순서를 알아내기 위해 느린 쿼리에 대한 명령입니다. 쿼리 계획에 Seq Scan가 표시되는 경우 , 인덱스가 사용되지 않고 있으며 쿼리를 변경하거나 새 인덱스를 추가해야 합니다.
다음은 조인을 사용한 또 다른 예입니다:
여기서는 user 테이블이 Collaboration 테이블과 조인됩니다. 쿼리 계획을 살펴보면 협업 테이블이 seq scan을 사용하고 있습니다. 먼저 실행 중입니다. 반면 사용자 테이블은 pkey를 사용하고 있습니다. 색인을 생성하고 나중에 실행 중입니다. user_id에 색인을 추가할 수 있습니다. 이 쿼리를 최적화하려면 협업 테이블의 열을 사용하세요. explain은 쿼리를 분석하는 데 도움이 되므로 최적화가 필요한 부분을 파악할 수 있습니다.
2. 주요 데이터베이스 지표 측정
쿼리 시간은 쿼리 성능을 확인하기 위해 측정할 수 있는 유일한 측정항목이 아닙니다. 다음을 포함한 여러 다른 데이터베이스 측정항목을 살펴보세요.
- CPU 사용량
- 메모리 사용량
- IO 대기를 위한 디스크 큐
- 인바운드 및 아웃바운드 트래픽을 위한 네트워크 대역폭
- 사용 가능한 디스크 공간
- 처리량
이러한 측정항목이 특정 임계값을 초과하면 쿼리 속도가 느려질 수 있습니다. 성능 문제를 이해하려면 특정 기간에 걸쳐 데이터 포인트를 살펴봐야 합니다.
측정해야 하는 데이터 포인트는 다음과 같은 다양한 요인에 따라 달라집니다.
-
데이터베이스 유형:
- 관계형
- 인메모리
- SQL 없음
- 데이터 웨어하우스
-
서버 호스팅 방법:
- 온프레미스
- 클라우드에서
데이터베이스 지표를 모니터링하는 단일 방법은 없으며 다양한 요인에 따라 다릅니다.
3. AppSignal을 사용하여 Rails 앱 성능 측정
모든 쿼리에 대한 가시성을 제공하는 중앙 위치 없이 모든 성능 지표를 관리하는 것은 어려울 수 있습니다. 모든 코드 블록에 성능 코드를 추가하는 것은 번거롭고 관리하기 어려울 수 있습니다.
AppSignal과 같은 도구를 사용하면 성능 측정을 애플리케이션에 쉽게 통합할 수 있습니다. AppSignal은 기본적으로 Rails를 지원합니다. 'Ruby용 AppSignal' 문서에서 간단한 AppSignal 설치 프로세스에 대해 알아보세요.
주목해야 할 중요한 측정항목은 다음과 같습니다.
- 느린 쿼리
- 처리량에 따른 데이터베이스 성능
- N+1 검색어
- 데이터베이스 지연 시간
- 활성 연결 수
AppSignal 대시보드는 다음과 같습니다:

Ruby on Rails 데이터베이스 성능을 최적화하는 7가지 방법
1. N+1 쿼리에 대한 즉시 로드
N+1 쿼리는 가장 일반적인 데이터베이스 성능 문제입니다. N+1의 예를 살펴보겠습니다. 사용자와 프로젝트라는 두 가지 모델이 있는 경우 쿼리:
이제 사용자 및 프로젝트 이름을 찾으려면 다음 코드를 실행하세요:
위의 코드는 각 루프에서 데이터베이스를 쿼리하여 성능 문제를 일으킵니다. 실행된 총 쿼리 수는 사용자 수 + 1이 됩니다.
이 문제를 제거하는 방법은 매우 간단합니다. 연결을 즉시 로드하면 됩니다. 간단히 .includes(:projects)을 추가하세요. 쿼리 끝에:
이제 위의 쿼리는 프로젝트를 로드하므로 루프를 실행하면 데이터베이스를 쿼리하지 않습니다.
Rails 6.1은 연결이 액세스되기 전에 즉시 로드되도록 보장하기 위해 엄격한 로드를 제공합니다. 엄격한 로딩을 활성화하려면 모델에 다음 줄을 추가하세요:
이제 즉시 로드 없이 프로젝트에 액세스하려고 하면 Rails에서 ActiveRecord::StrictLoadingViolationError가 발생합니다. 예외입니다.
Rails 6.1이 없으면 Bullet과 같은 gem을 사용할 수 있습니다.
2. 데이터베이스 색인 사용
데이터베이스는 데이터를 더 빠르게 검색할 수 있도록 인덱스를 제공합니다. 앞서 설명한 explain 명령을 사용하면 쿼리가 적절한 인덱스를 사용하고 있는지 확인할 수 있습니다.
이미 존재하는 인덱스나 성능 향상에 도움이 되는 추가 인덱스를 사용하도록 느린 쿼리를 변경할 수 있습니다.
MySQL에는 네 가지 유형의 인덱스가 있습니다:
- 기본 키 - 색인이 기본 키에 자동으로 추가되어 고유함도 보장됩니다.
- 고유 - 고유 키 인덱스는 속성에 추가된 항목이 항상 고유함을 보장합니다.
- 색인 - 기본 키 이외의 속성에 추가됨
- 전체 텍스트 - 문자 기반 데이터에 대한 쿼리에 도움이 됩니다.
인덱스는 B-Tree 또는 Hash 형식으로 저장됩니다.
인덱스는 단일 필드에 추가하거나 여러 필드의 구성으로 생성할 수 있습니다. 복합 인덱스는 여러 필드가 포함된 쿼리를 최적화하는 데 유용합니다. 하나의 인덱스만 사용하는 경우 대규모 데이터세트 스캔이 필요합니다.
예를 들어 다음 쿼리에는 두 개의 필드가 있습니다.
"abc" 프로젝트에 많은 사용자가 있을 수 있습니다. 국가 필드가 스캔됩니다. 결과 데이터세트가 크기 때문에 프로세스가 느려질 수 있습니다. 이 경우 프로젝트 및 국가 필드 모두에 복합 색인을 추가하여 성능을 향상시킬 수 있습니다.
다음 ActiveRecord 마이그레이션 명령을 사용하여 Rails에 인덱스를 추가할 수 있습니다:
단일 인덱스:
복합 색인:
3. 사용 한도
반환되는 레코드가 많을수록 성능이 느려질 수 있습니다. 대규모 데이터 세트를 반환하는 단일 쿼리보다 여러 쿼리를 수행하는 것이 더 좋습니다.
다음 100개의 배치를 가져오려면 오프셋을 사용할 수 있습니다:
이렇게 하면 성능이 크게 향상됩니다. 한 가지 명심해야 할 점은 오프셋이 높을수록 쿼리 속도가 느려진다는 것입니다. 오프셋에 제한을 추가합니다.
4. find_each을 사용하세요 많은 수의 항목을 로드하려면
레코드를 반복할 때 더 나은 성능을 위해 Rails에서 일괄 처리하세요:
이렇게 하면 데이터베이스의 모든 레코드를 한 번 쿼리하여 메모리 및 데이터베이스 성능 문제가 발생합니다.
find_each 사용 또는 find_in_batches 동일한 작업을 일괄적으로 수행하여 성능을 향상시키는 데 도움이 됩니다:
기본적으로 find_each 쿼리 결과는 1,000개의 일괄 처리입니다. 인수로 정의하여 배치 크기를 변경할 수 있습니다:
find_in_batches을 사용할 수도 있습니다. 수행해야 하는 작업을 기반으로 합니다. find_in_batches의 차이점 및 find_each 그거 find_in_batches야? 개별 기록이 아닌 모델 배열로 결과를 산출합니다.
5. Pluck을 사용하여 필수 필드를 선택하세요
Pluck 명령은 쿼리 결과를 ActiveRecord 개체 대신 배열로 직접 변환합니다.
쿼리가 큰 결과를 반환하는 경우 Pluck을 사용하면 코드 성능이 향상됩니다. Pluck은 데이터베이스에서 필수 필드만 선택합니다:
결과는 기본 테이블이 아닌 인덱스에서 가져오며 정렬과 관련된 쿼리에 더 효과적입니다.
6. 대량 작업 사용
대량 삭제 ActiveRecord 개체를 반복하는 삭제 작업은 한 번에 하나씩 레코드를 삭제합니다:
각 레코드를 삭제하려면 데이터베이스에 대해 많은 쿼리를 수행해야 합니다. 대신 단일 대량 delete_all을 사용하는 것이 가장 좋습니다. 쿼리:
대량 생성 일부 사람들은 대량 삭제와 유사하게 ActiveRecord를 사용하여 대량 삽입을 수행할 수도 있다는 사실을 인식하지 못합니다. 이렇게 하면 n를 줄일 수 있습니다. 쿼리 수는 단 하나입니다. ActiveRecord::Base create 메소드는 해시 배열을 입력으로 받아들입니다:
7. 필요한 경우 인메모리 계산 사용
어떤 경우에는 쿼리보다 메모리 내 계산이 더 좋습니다. 데이터베이스에서 사용자 기록이 없는 국가를 찾고 싶다고 가정해 보겠습니다.
위 쿼리에서는 결과를 얻으려면 N개의 쿼리가 필요했습니다. 대신, 특정 국가의 사용자를 찾고 메모리에서 다른 계산을 수행하는 단일 쿼리를 작성할 수 있습니다.
요청-응답 주기를 재사용하고 경우에 따라 데이터베이스 부하를 줄이기 위해 캐시할 수 있습니다. Rails는 페이지, 액션, 조각 캐싱이라는 세 가지 유형의 캐싱 기술을 제공합니다(조각 캐싱은 기본적으로 제공됨).
마무리:ActiveRecord 및 AppSignal을 사용하여 Ruby on Rails 성능 최적화
좋아요, 요약할 시간이에요! 이 게시물에서는 다음과 같이 Rails에서 데이터베이스 성능 문제를 식별하고 테스트하는 세 가지 방법을 다루었습니다.
- ActiveRecord 쿼리에 대한 설명 실행
- 주요 데이터베이스 측정항목 측정
- AppSignal을 사용하여 Rails 앱 성능 측정
다음을 포함하여 데이터베이스 성능을 최적화하는 7가지 방법:
- N+1 쿼리에 대한 즉시 로드
- 데이터베이스 색인
- 한도
find_each많은 수의 항목을 로드하려면- 필수 입력란을 선택하여 선택
- 대량 작업
- 인메모리 계산
Rails를 사용하면 애플리케이션 개발이 매우 쉽고 빠릅니다. ActiveRecord는 데이터베이스 코드의 생산성, 재사용성 및 유지 관리에 도움이 됩니다. ActiveRecord 쿼리가 어떻게 SQL 쿼리로 변환되고 실행되는지 이해하는 것이 중요합니다.
그러나 Rails 데이터베이스 성능을 최적화하는 데 필요한 가장 중요한 것은 성능 데이터에 대한 가시성입니다. 성능 문제는 흔히 발생하지만 이러한 가시성이 확보되면 문제를 해결할 수 있습니다. 데이터베이스 메트릭을 제공하는 적절한 모니터링 도구가 필요합니다. 우리는 AppSignal을 좋아합니다;)
추신 Ruby Magic 게시물이 보도되는 즉시 읽으려면 Ruby Magic 뉴스레터를 구독하고 단 하나의 게시물도 놓치지 마세요!