미래 지향적인 웹 앱 구축: The Codest의 전문가 팀이 제공하는 인사이트
The Codest가 최첨단 기술로 확장 가능한 대화형 웹 애플리케이션을 제작하고 모든 플랫폼에서 원활한 사용자 경험을 제공하는 데 탁월한 성능을 발휘하는 방법을 알아보세요. Adobe의 전문성이 어떻게 디지털 혁신과 비즈니스를 촉진하는지 알아보세요...
성능은 웹 애플리케이션을 개발할 때 고려해야 할 가장 중요한 측면 중 하나입니다. 데이터베이스에서 데이터를 가져오는 방법을 분석하는 것은 개선점을 찾을 때 좋은 출발점입니다. 이 글에서는 데이터베이스 수준에서 집계 함수를 사용하고 데이터를 필터링하여 성능을 개선하는 방법에 대한 예제를 살펴봅니다.
이 글은 제가 실제로 겪었던 문제에서 영감을 받았습니다. 그 문제를 해결하면서 많은 것을 배웠고 지금도 그 문제를 참고하고 있습니다. 사례는 좋은 학습 자료라고 생각하며 많은 것을 명확하게 해줄 수 있습니다. 이 글에서는 활성 레코드 쿼리 방법을 사용하는 몇 가지 예를 공유하고자 합니다.
도메인별 세부 사항을 소개하지 않기 위해 라이브러리용 샘플 애플리케이션을 사용하여 예시를 설명하겠습니다. 아래 다이어그램에서 볼 수 있듯이 매우 간단합니다. 저자, 도서, 사용자, 대출의 네 가지 테이블이 있습니다. 한 명의 사용자가 여러 권의 책을 빌릴 수 있고 한 권의 책을 여러 사용자가 빌릴 수 있으므로 다대다 관계를 모델링하기 위해 조인 테이블이 필요합니다. 이 경우의 조인 테이블이 바로 대여 테이블입니다. 또한 대여 및 반납 날짜와 같은 몇 가지 추가 정보도 여기에 저장합니다. 저자는 자신의 이름에 여러 권의 책을 할당할 수 있습니다. 책에는 장르를 정의하는 속성도 있습니다.
이 작업은 한 명의 사용자에 대한 통계를 준비하여 각 장르에서 얼마나 많은 책을 빌렸는지 파악하는 것이었습니다. 가장 먼저 생각한 것은 사용자가 대출한 모든 책을 가져와서 장르별로 그룹화한 다음 매핑을 수행하여 각 장르에 목록이 아닌 책 수가 할당되도록 하는 것이었습니다. 제가 생각해낸 방법은 다음과 같습니다:
Hash[Book.joins(:rentals).where(rentals: { user: user }).group_by(&:genre).map { |genre, books| [genre, books.size] }]
이 접근 방식은 작동하고 깔끔해 보이지만, 액티브 레코드 쿼리 방법이 제공하는 모든 가능성을 활용하지는 못합니다. 덕분에 원시 SQL을 직접 사용하지 않고도 데이터베이스 수준에서 데이터를 필터링하고 집계할 수 있습니다. 코드. DB 수준에서 운영하면 효율성도 높아집니다.
위의 예제에서는 루비의 그룹 대신 그룹 메서드를 사용할 수 있습니다.메서드별. GROUPBY 절을 tSQL 쿼리에 추가할 수 있습니다. 또한 매핑 및 크기 메서드는 카운트 집계 함수로 대체할 수 있습니다. 결국 다음과 같은 쿼리가 남게 됩니다:
Book.joins(:rentals).where(rentals: { user: user }).group(:genre).count(:books)
훨씬 더 간단해 보입니다!
아래에서 제가 알아두면 도움이 될 만한 다른 쿼리 방법 몇 가지를 소개합니다.
작업: 책을 빌린 적이 없거나 빌린 지 1년이 지난 사용자를 필터링하세요.
관련 렌탈을 포함하여 모든 사용자를 가져온 다음 선택 방법을 사용하여 필터링할 수 있습니다.
사용자.포함(:렌탈).선택 do |사용자|
user.rentals.empty? || user.rentals.none? { |rental| rental.start_date >= Date.today - 1.year }
end
물론 모든 것을 가져올 필요는 없습니다. 쿼리 방법을 사용하면 DB 수준에서 필터링할 수 있습니다. 먼저 작년에 책을 빌린 적이 있는 사용자를 선택한 다음 최종 선택에서 제외해 보겠습니다.
하위 쿼리는 다음과 같이 표시됩니다:
User.joins(:rentals).where(rentals: { start_date: (Date.today - 1.year).Date.today })
이제 이 모든 것을 종합해 보겠습니다:
User.where.not(id: [User.joins(:rentals).where(rentals: { start_date: (Date.today - 1.year)..Date.today })])
과제: 대출 도서가 1권 또는 0권인 저자 확보하기
선택 방법을 사용하면 매우 간단하지만, 다시 말하지만 DB에서 필터링할 수 있으므로 큰 데이터 집합에 대해 작업할 필요가 없습니다:
저자.포함(:책).선택 { |저자| 저자.책.크기 <= 1 } }
그러면 할당된 책이 0권인 저자를 빠르고 쉽게 필터링할 수 있습니다:
Author.left_joins(:books).where(books: { id: nil })
왼쪽_조인(및 일반적으로 외부 조인)을 사용할 때 한 가지 기억해야 할 중요한 사항이 있습니다. 왼쪽 테이블(여기서는 authors)에 해당하는 레코드가 오른쪽 테이블(여기서는 books)에 없는 레코드가 있는 경우 결과적으로 오른쪽 테이블 열이 nil 값으로 채워집니다.
시스템에서 하나의 책이 할당된 저자도 필요하므로 몇 가지 작업을 더 수행해야 합니다. 그룹화, 계산 및 조건 추가 작업을 수행해야 합니다. 이 모든 작업을 수행하는 방법은 다음과 같습니다:
Author.left_joins(:books).group(:id).having("count(*) <= ?", 1)
조건은 집계 함수 뒤에 오므로 이를 지정하려면 WHERE 절 대신 HAVING 절을 사용해야 합니다.
애플리케이션 성능을 고려할 때 액티브 레코드 쿼리 메서드를 확인해 볼 가치가 있습니다. 코드를 간소화하고 더 빠르게 작동하도록 만들 수 있습니다. 공유한 예제가 쿼리 메서드가 제공하는 가능성을 탐색하는 데 도움이 되길 바랍니다.
자세히 읽어보세요:
– 새로운 현실을 맞이할 시간입니다. 원격 근무의 시대가 한 달 전부터 시작되었습니다.
– Rails 앱에서 일반적인 JS 프레임워크를 사용해야 하나요? Stimulus.js가 대안이 될 수 있습니다.