0

나는 인보이스 및 지불에 대한 간단한 정규화 모델을 가지고 있습니다.Ruby on Rails에서 미 지불 금액에 denormaized 필드를 사용해야합니까?

관련 필드는 관계가

Invoice 
    has_many :invoice_payments 
    has_many :payments, through: :invoice_payments 

InvoicePayment 
    belongs_to :invoice 
    belongs_to :payment 

Payment 
    has_many :invoice_payments 
    has_many :invoices, through: :invoice_payments 

있는 결제 모델이 질문에 관련이 없습니다하지만 같은 문제를 전시

invoices.id 
invoices.amount_with_tax 
invoice_payments.id 

invoice_payments.invoice_id 
invoice_payments.amount 

있습니다.

변수 invoices@invoices은 ActiveRecord 관계입니다.

invoices.where('amount_outstanding > 0') 

하지만 비정규 필드의 유지는 귀찮은입니다 : 내가 무급 청구서를 얻기 위해 송장 테이블에 코드를 amount_outstanding 필드를 추가하는 경우

은 간단하다. 해당 필드없이이를 얻을 수

내 현재 코드는 복잡하다 : 나는 여기에 대한 성능 테스트를 수행하지 않은

invoices = invoices.left_outer_joins(:invoice_payments) 
invoices = invoices.distinct.select('invoices.*, sum(invoice_payments.amount) as total_payments') 
invoices = invoices.group('invoices.id')  
invoices = invoices.having('sum(invoice_payments.amount) < invoices.amount_with_tax or sum(invoice_payments.amount) is null') 

하지만 많은있을 때 매우 좋은하지 않습니다 것 같습니다 시스템의 송장. ActiveRecord에 의해 생성 된 코드는 SQL에서 작성하는 코드와 비슷하므로 끔찍하지는 않습니다.

송장에 완전히 설명되지 않은 지불을 찾으려면 지불 측에서 유사한 코드가 필요합니다.

미결제 인보이스를 찾는 것은 미결제 금액을보고하는 것과 같이 빈번한 작업입니다. 잘 운영되는 회사의 경우 미수금 계정의 금액은 지급 된 금액보다 적습니다. 시간이 지남에 따라 전체 인보이스 중 훨씬 작은 비율이됩니다.

일반적으로 인보이스에 지불하는 것은 한 번만 수행되며 거의 되돌리거나 수정하지 않습니다. 대부분의 지불은 하나의 인보이스와 관련이 있으며 완전히 처리합니다.

또한 미지급 인보이스가 있는지 또는 해당 금액이 erb에 있는지 확인하려고 시도합니다. 예 : <%[email protected] %>은 SQL 오류를 반환합니다.

개인적으로 비정규 화 된 데이터는 유지 보수 작업이 정규화 된 상태로 유지되는 작업의 약 3 배이기 때문에 개인적으로 비표준화 된 데이터가 마음에 들지 않습니다. 이 경우 amount_with_tax이 변경되거나 InvoicePayment이 편집되거나 삭제되거나 다른 송장으로 이동 된 경우 필드가 업데이트되어야합니다. amount_outstanding의 값을 계산하는 코드는 단 하나의 송장에 대한 매우 간단하다 : 나는 현재 amount_outstanding을 유지하기 위해 송장에 콜백 및 InvoicePayments 모델을 사용하고

paid = invoice_payments.sum(:amount) 
self.amount_outstanding = self.amount_with_tax - paid 
save 

.

그래서이 질문에 답할만한 가치가있는 비정규 화 된 필드가 있습니까? 아니면 이것을 달성하는 더 좋은 방법이 있습니까?

답변

1

미결제 금액을 표시하거나 의존하는 사용 사례에 많이 달려 있습니다. 이 값을 얼마나 자주 사용합니까? 사용자가 페이지에서 다른 모든 정보를 즉시 표시 할 수있을 때이 값을 표시하기 위해 지연 시간을 거의 고려하지 않습니다 (이 값을 계산하는 것이 느리다고 간주).

귀하는이 시나리오에 대한 성능 테스트를 수행하지 않았으며 처리 된 송장 수에 대한 시스템 범위에 대한 정보도 없다고 말씀하셨습니다. 모든 금융 시스템과 마찬가지로 모든 거래는 특정 재무 기간과 관련이 있기 때문에 시스템에 저장된 모든 송장 대신 해당 기간을 고려하여 성과 요구에 액세스하는 것이 더 적절합니다.

일반적으로 비정규 화 필드가 필요없는 처리는 상당히 많은 인보이스를 처리 할 수 ​​있어야하며 물론 서버 설정에 따라 달라집니다. 또한 동일한 기능을 사용하기 위해 코드를 최적화하고 쿼리 수를 줄일 수있는 가능성이 있습니다.

성능에 대한 문제를 아직 보지 못한 경우 조기 최적화를 시도하는 것이 좋습니다 (항상 권장되는 것은 아닙니다). 그래서 필자는 필자가 필요로 할 때까지 비정규 화 된 필드를 피한 다음 필요에 따라 필요한 최적화를 수행 할 것을 고려할 것이다. 희망이 도움이됩니다.

+0

인보이스 업데이트에 대한 쿼리 빈도는 아마도 약 100 : 1입니다. 시스템의 최종 크기는 알 수 없지만 확장 기능을 제한하고 싶지는 않습니다. 전형적인 소규모 회사의 경우 1 년에 수천 통의 인보이스가있을 수 있지만별로 크지 않습니다. 정규화 된 코드는 카운트를 얻는 오류를 제외하고 실행되며 그에 대한 또 다른 쿼리를 작성할 수 있습니다. 조기 최적화에 대해서는 DK에 동의합니다. –

+0

수천 개의 인보이스는 큰 수치가 아니므로 비정규 필드없이 시작하는 것이 더 좋은 옵션으로 보이고 필요에 따라 최적화 작업을 수행하십시오. 또한 카운트의 경우 코드를 작성하여 모델 또는 컨트롤러에서 카운트 한 다음 erb에 직접 코드를 작성하는 대신 erb에 값을 전달하는 것이 더 좋습니다. – coffeebytes