[java] SQL과 응용 프로그램의 계산 수행의 장단점은 무엇입니까?

shopkeeper 표에는 다음과 같은 필드가 있습니다.

id (bigint),amount (numeric(19,2)),createddate (timestamp)

위의 테이블이 있다고 가정 해 봅시다. 어제 레코드를 가져 와서 센트로 인쇄하여 보고서를 생성하고 싶습니다.

한 가지 방법은 내 Java 응용 프로그램에서 계산을 수행하고 간단한 쿼리를 실행하는 것입니다.

Date previousDate ;// $1 calculate in application

Date todayDate;// $2 calculate in application

select amount where createddate between $1 and $2 

그런 다음 레코드를 반복하고 Java 응용 프로그램에서 금액을 센트로 변환하고 보고서를 생성합니다.

다른 방법은 SQL 쿼리 자체에서 계산을 수행하는 것과 같습니다.

select cast(amount * 100 as int) as "Cents"
from shopkeeper  where createddate  between date_trunc('day', now()) - interval '1 day'  and  date_trunc('day', now())

그런 다음 레코드를 반복하고 보고서를 생성하십시오.

한 가지 방법으로, 모든 처리는 Java 응용 프로그램에서 수행되며 간단한 쿼리가 발생합니다. 다른 경우에는 모든 변환 및 계산이 SQL 쿼리에서 수행됩니다.

위의 사용 사례는 예일 뿐이며 실제 시나리오에서는 테이블에 유사한 종류의 처리가 필요한 많은 열이있을 수 있습니다.

성능 및 기타 측면에서 어떤 접근 방식이 더 나은지, 왜 그런지 말해 주시겠습니까?



답변

그것은 많은 요인에 달려 있지만 가장 중요한 것은 다음과 같습니다.

  • 계산의 복잡성은 (그 규모 때문에, 응용 프로그램 서버에 복잡한 사각 사각을하고 선호 밖으로 오히려 확장되는 DB 서버보다 최대 )
  • 데이터 양 (많은 데이터에 액세스 / 집계해야하는 경우 db 서버에서 수행하면 대역폭이 절약되고 인덱스 내에서 집계를 수행 할 수있는 경우 디스크 io)
  • 편의성 (SQL은 복잡한 작업에 가장 적합한 언어는 아닙니다. 특히 절차 작업에는 적합하지 않지만 세트 기반 작업에는 적합합니다.

당신이 경우 언제나처럼, 열과 행을, 응용 프로그램 서버에 데이터를 다시 가져 최소화 당신의 이점에있을 것입니다. 쿼리를 조정하고 적절하게 색인을 작성하면 두 시나리오에 도움이됩니다.

다시 참고하십시오 :

그런 다음 레코드를 반복합니다.

레코드를 반복 하는 것은 거의 항상 SQL에서 잘못된 일입니다. 집합 기반 작업을 작성하는 것이 좋습니다.

일반적으로 데이터베이스 작업을 최소 “이 데이터 저장,이 데이터 가져 오기”로 유지하는 것이 좋습니다. 그러나 서버의 우아한 쿼리가 많은 대역폭을 절약 할 수있는 시나리오의 예는 항상 있습니다.

또한 계산 비용이 비싼 경우 어딘가에 캐시 할 수 있습니까?

정확한 “더 나은” 것을 원한다면 ; 두 가지 방법으로 코딩하고 비교하십시오 (둘 중 첫 번째 초안은 100 % 조정되지 않았을 것입니다). 그러나 일반적인 사용법을 고려하십시오. 실제로 실제로 한 번에 5 번 (별도로) 호출되는 경우 다음을 시뮬레이트합니다. 하나의 “1 대 1″만 비교하지 마십시오.


답변

은유를 사용해 봅시다. 파리에서 황금 목걸이 를 사려면 금세 공인이 케이프 타운이나 파리에 앉아있을 수 있습니다. 그것은 기술과 맛의 문제입니다. 그러나 당신은 그것을 위해 남아프리카에서 프랑스로 금광을 절대로 보내지 않을 것 입니다. 광석은 채굴 현장 (또는 적어도 일반 지역)에서 처리되며 금만 배송됩니다. 앱과 데이터베이스도 마찬가지입니다.

지금까지로 PostgreSQL의이 우려, 당신은 아주 효율적으로, 서버에서 거의 모든 작업을 수행 할 수 있습니다. RDBMS는 복잡한 쿼리에 탁월합니다. 절차 상 필요에 따라 tcl, python, perl 등 다양한 서버 측 스크립트 언어 중에서 선택할 수 있습니다 . 대부분 PL / pgSQL을 사용 합니다.

최악의 시나리오는 더 큰 세트의 모든 단일 행마다 서버로 반복적으로 이동하는 것입니다. (한 번에 1 톤의 광석을 운송하는 것과 같습니다.)

두 번째 인라인 은 이전의 쿼리에 따라 일련의 쿼리를 보내면 모든 쿼리는 서버에서 하나의 쿼리 또는 절차로 수행 할 수 있습니다. (즉, 금과 각 보석을 별도의 선박으로 순차적으로 운송하는 것과 같습니다.)

앱과 서버 사이를 오가는 비용이 많이 듭니다. 서버 클라이언트 용. 이를 줄이려고하면 서버 측 프로 시저 및 / 또는 필요한 경우 정교한 SQL을 사용하는 것이 좋습니다.

우리는 거의 모든 복잡한 쿼리를 Postgres 함수로 압축 한 프로젝트를 마쳤습니다. 앱은 매개 변수를 넘겨 받아 필요한 데이터 세트를 얻습니다. 빠르고, 깨끗하고, 단순하며 (앱 개발자를 위해) I / O는 최소한으로 감소했습니다. 탄소 발자국이 적은 반짝이는 목걸이입니다.


답변

이 경우는 아마 데이터베이스 엔진이 자바보다 더 효율적 소수점 연산 루틴을 가질 가능성이 높습니다로 약간 더 나은 SQL에서 계산을 끕니다.

일반적으로 행 수준 계산의 경우 큰 차이가 없습니다.

차이가 나는 곳은 다음과 같습니다.

  • SUM (), AVG (), MIN (), MAX ()와 같은 집계 계산은 데이터베이스 엔진이 Java 구현보다 훨씬 빠릅니다.
  • 어디서나 계산은 행을 필터링하는 데 사용됩니다. DB에서 필터링하는 것은 행을 읽은 다음 버리는 것보다 훨씬 효율적입니다.

답변

SQL에서 수행해야 할 데이터 액세스 논리 부분과 응용 프로그램에서 수행해야 할 부분에 대해서는 흑백이 없습니다. 나는 Mark Gravell의 표현을 좋아합니다.

  • 복잡한 계산
  • 데이터 집약적 인 계산

SQL의 강력 함과 표현력은 과소 평가되었습니다. 윈도우 함수 가 도입 되었으므로 데이터베이스에서 엄격하지 않은 설정 지향 계산을 매우 쉽고 우아하게 수행 할 수 있습니다.

전반적인 애플리케이션 아키텍처에 관계없이 항상 세 가지 규칙을 따라야합니다.

  • 데이터베이스와 애플리케이션간에 전송되는 데이터의 양을 줄이십시오 (DB의 데이터 계산에 유리함)
  • 데이터베이스에 의해 디스크에서로드 된 데이터의 양을 줄입니다 (데이터베이스가 불필요한 데이터 액세스를 피하도록 명령문을 최적화하도록 유리함)
  • 복잡한 동시 계산을 통해 데이터베이스를 CPU 한도까지 푸시하지 마십시오 (데이터를 응용 프로그램 메모리로 가져 와서 계산 수행).

내 경험상, 적절한 DBA와 괜찮은 데이터베이스에 대한 약간의 지식이 있으면 곧 DB CPU 한계에 빠지지 않을 것입니다.

이 부분들을 설명하는 추가 자료 :


답변

일반적으로 같은 프로젝트 또는 다른 프로젝트의 다른 모듈이나 구성 요소가 이러한 결과를 얻어야 할 가능성이있는 경우 SQL로 작업을 수행하십시오. 추가 작업없이 최종 값을 얻기 위해 모든 db 관리 도구에서 저장된 proc을 호출하면되기 때문에 서버 측에서 원자 적 작업이 더 좋습니다.

경우에 따라 적용되지 않지만 의미가있는 경우에는 적용됩니다. 또한 일반적으로 db 상자는 최상의 하드웨어 및 성능을 갖습니다.


답변

ORM을 기반으로 작성하거나 캐주얼 한 저 성능 응용 프로그램을 작성하는 경우 응용 프로그램을 단순화하는 패턴을 사용하십시오. 고성능 애플리케이션을 작성하고 스케일에 대해 신중하게 생각하는 경우 처리를 데이터로 이동하여 이길 수 있습니다. 처리를 데이터로 옮기는 것을 강력히 권합니다.

(1) OLTP (소수의 레코드) 트랜잭션 두 가지 단계로 이에 대해 생각해 봅시다. (2) OLAP (많은 레코드의 긴 스캔).

OLTP의 경우 속도를 높이려면 (초당 10k-100k 트랜잭션) 데이터베이스에서 래치, 잠금 및 교착 상태 경합을 제거해야합니다. 이것은 트랜잭션에서 긴 지연을 제거해야 함을 의미합니다. 클라이언트에서 DB 로의 왕복 이동은 클라이언트로 처리를 이동하는 것이 긴 지연 중 하나입니다. 읽기 / 업데이트 원자를 만들기 위해 오래 지속 된 트랜잭션을 가질 수 없으며 처리량이 매우 높습니다.

다시 : 수평 스케일링. 최신 데이터베이스는 수평 적으로 확장됩니다. 이러한 시스템은 이미 HA 및 내결함성을 구현합니다. 이를 활용하여 애플리케이션 공간을 단순화하십시오.

OLAP을 살펴 보자.이 경우 테라 바이트 단위의 데이터를 응용 프로그램으로 다시 끌어 오는 것이 끔찍한 아이디어라는 것이 분명해야합니다. 이 시스템은 압축 된 사전 구성된 컬럼 데이터에 대해 매우 효율적으로 작동하도록 특별히 설계되었습니다. 최신 OLAP 시스템은 또한 수평 적으로 확장되며 작업을 수평으로 분산시키는 정교한 쿼리 플래너 (내부로 처리를 데이터로 이동)를 가지고 있습니다.


답변

프런트 엔드 또는 백엔드에서 계산을 수행할지 여부는 비즈니스 구현에서 목표를 결정할 수 있는지 여부에 따라 결정됩니다. 때때로 자바 코드는 잘 작성된 SQL 코드보다 성능이 좋을 수도 있고 그 반대 일 수도 있습니다. 그러나 여전히 혼란 스러우면 먼저 결정하려고 할 수 있습니다.

  1. 데이터베이스 sql을 통해 간단한 것을 얻을 수 있다면 db가 훨씬 더 잘 수행하고 계산을 수행 한 다음 결과 가져 오기로 더 잘 수행하십시오. 그러나 실제 계산에 여기에서 너무 많은 계산이 필요한 경우 응용 프로그램 코드를 사용할 수 있습니다. 왜? 대부분의 경우 시나리오는 루핑과 같이 프론트 엔드 언어가 이러한 것들을 위해 더 잘 설계된 SQL에서 가장 잘 처리되지 않기 때문입니다.
  2. 많은 장소에서 유사한 계산이 필요한 경우 계산 코드를 db 끝에 배치하는 것이 동일한 장소에 물건을 보관하는 것이 좋습니다.
  3. 많은 다른 쿼리를 통해 최종 결과를 얻기 위해 계산을 많이 해야하는 경우 백엔드에서 결과를 검색 한 다음 전면에서 계산하는 것보다 더 나은 수행을 위해 저장 프로 시저에 동일한 코드를 배치 할 수 있으므로 db end도 진행합니다 종료.

코드를 배치 할 위치를 결정하기 전에 생각할 수있는 다른 많은 측면이 있습니다. 한 가지 인식이 완전히 잘못되었습니다-모든 것이 Java (앱 코드)에서 가장 잘 수행 될 수 있으며 모든 것이 db (sql 코드)로 수행되는 것이 가장 좋습니다.