하나의 큰 쿼리 또는 많은 작은 쿼리가 더 빠릅니다. 있으며, 그들 중 일부는 모든 “상대적”과 함께

나는 다른 회사에서 일하고 있으며, 그들 중 일부는 모든 “상대적”과 함께 테이블을 조인하는 뷰를 선호한다는 것을 알았습니다. 그러나 응용 프로그램에서 때로는 하나의 열만 사용하면됩니다.

따라서 간단한 선택을 한 다음 시스템 코드에서 “결합”하는 것이 더 빠를까요?

시스템은 php, java, asp, 데이터베이스에 연결되는 모든 언어 일 수 있습니다.

그래서 문제는 서버 측 (php, java, asp, ruby, python …)에서 데이터베이스로가는 것이 무엇입니까? 우리가 필요한 모든 것을 얻거나 서버 측에서 데이터베이스로 이동하여 한 번에 하나의 테이블에서만 열을 가져 오는 쿼리?



답변

귀하의 질문을 다루는 것은 주제 분해 참여입니다.

이 책의 209 페이지 에 따르면

고성능 MySQL

다중 테이블 조인 대신 여러 단일 테이블 쿼리를 실행 한 다음 응용 프로그램에서 조인을 수행하여 조인을 분해 할 수 있습니다. 예를 들어,이 단일 쿼리 대신 :

SELECT * FROM tag
JOIN tag_post ON tag_post.tag_id = tag.id
JOIN post ON tag_post.post_id = post.id
WHERE tag.tag = 'mysql';

다음 쿼리를 실행할 수 있습니다.

SELECT * FROM tag WHERE tag = 'mysql';
SELECT * FROM tag_post WHERE tag_id=1234;
SELECT * FROM post WHERE post.id IN (123,456,567,9098,8904);

왜 지구상에서 이것을 하시겠습니까? 아무것도 보지 않고 쿼리 수를 늘 렸기 때문에 언뜻보기에는 낭비로 보입니다. 그러나 이러한 구조 조정은 실제로 상당한 성능 이점을 제공 할 수 있습니다.

  • 캐싱이 더 효율적일 수 있습니다. 많은 응용 프로그램이 테이블에 직접 매핑되는 “개체”를 캐시합니다. 이 예제에서 태그 mysql가 있는 객체 가 이미 캐시 된 경우 응용 프로그램은 첫 번째 쿼리를 건너 뜁니다. 캐시에서 ID가 123, 567 또는 908 인 게시물을 찾으면 IN()목록 에서 제거 할 수 있습니다 . 쿼리 캐시도이 전략의 이점을 활용할 수 있습니다. 테이블 중 하나만 자주 변경되면 조인을 분해하면 캐시 무효화 수가 줄어들 수 있습니다.
  • 쿼리를 개별적으로 실행하면 잠금 경합이 줄어들 수 있습니다.
  • 응용 프로그램에서 조인을 수행하면 다른 서버에 테이블을 배치하여 데이터베이스를 쉽게 확장 할 수 있습니다.
  • 쿼리 자체가 더 효율적일 수 있습니다. 이 예제에서 IN()조인 대신 목록을 사용하면 MySQL이 조인에서 가능한 것보다 행 ID를 정렬하고 행을보다 최적으로 검색 할 수 있습니다.
  • 중복 행 액세스를 줄일 수 있습니다. 응용 프로그램에서 조인을 수행한다는 것은 각 행을 한 번만 검색하는 것을 의미하지만 쿼리의 조인은 본질적으로 동일한 데이터에 반복적으로 액세스 할 수있는 비정규 화입니다. 같은 이유로 이러한 구조 조정은 전체 네트워크 트래픽 및 메모리 사용량을 줄일 수도 있습니다.
  • 어느 정도까지는이 기술을 MySQL이 조인을 실행하는 데 사용하는 중첩 루프 알고리즘 대신 해시 조인을 수동으로 구현하는 것으로 볼 수 있습니다. 해시 조인이 더 효율적일 수 있습니다.

결과적으로, 이전 쿼리의 많은 데이터를 캐시하고 재사용 할 때, 여러 서버에 데이터를 분배 IN()하거나, 조인을 목록으로 바꾸 거나, 조인이 동일한 테이블을 여러 번 참조 할 때 애플리케이션에서 조인을 수행하는 것이 더 효율적일 수 있습니다 .

관찰, 관측

InnoDB가 쿼리 캐시를 교차 검사 할 때 약간 무겁기 때문에 첫 번째 글 머리 기호가 마음에 듭니다.

마지막 글 머리 기호에 관해서는 2013 년 3 월 11 일 에 중첩 루프 알고리즘을 설명 하는 게시물을 작성했습니다 ( JOIN 조건과 WHERE 조건 사이에 실행 차이가 있습니까? ). 읽은 후에는 조인 분해가 얼마나 좋은지 알 수 있습니다.

책의 다른 모든 요점 과 관련하여 개발자는 실제로 성능을 최우선으로 생각합니다. 일부는 빠른 디스크 사용, 더 많은 CPU / 코어 가져 오기, 스토리지 엔진 조정 및 구성 파일 조정과 같은 성능 향상을 위해 외부 응용 프로그램 (응용 프로그램 외부)에 의존합니다. 다른 사람들은 버클을 짜서 더 나은 코드를 작성합니다. 일부는 저장 프로 시저에서 모든 비즈니스 인텔리전스를 코딩하는 데 의존하지만 조인 분해를 적용하지 않습니다 ( 데이터베이스 계층에서 응용 프로그램 논리를 반대하거나 다른 게시물과 함께 무엇을 주장합니까? 참조). 각 개발자 상점의 문화와 관용에 달려 있습니다.

일부는 성능에 만족하고 더 이상 코드를 건드리지 않을 수 있습니다. 다른 사람들은 컴포지션에 참여하려고 할 때 얻을 수있는 큰 이점이 있다는 것을 깨닫지 못합니다.

기꺼이 개발자를 위해 …

시도 해봐 !!!


답변

에서 포스트 그레스 (그리고 아마도 비슷한 정도에 대한 RDBMS는 낮은 정도 MySQL은), 적은 수의 쿼리는 거의 항상 빨리.

여러 쿼리를 구문 분석하고 계획하는 오버 헤드는 이미 대부분의 경우 얻을 수있는 것 이상입니다.

클라이언트에서 수행해야 할 추가 작업에 대해 말하지 말고 결과를 결합하면 일반적으로 속도 가 훨씬 느려집니다. RDBMS는 이러한 종류의 작업과 작업이 원본 데이터 형식을 기반으로하는 것을 전문으로합니다. text중간 결과를 캐스트 하거나 클라이언트의 기본 유형으로 변환하지 않아 결과가 덜 정확하거나 잘못 될 수 있습니다. 부동 소수점 숫자를 생각해보십시오 …

또한 DB 서버와 클라이언트간에 더 많은 데이터를 전송합니다. 이것은 값으로 가득 찬 손에는 무시할 수 있거나 큰 차이를 만듭니다.

여러 쿼리가 데이터베이스 서버에 대한 여러 번의 왕복을 의미하는 경우 네트워크 대기 시간 및 트랜잭션 오버 헤드, 연결 오버 헤드까지 여러 번 수집합니다. 큰 손실.

설정에 따라 네트워크 대기 시간만으로 나머지 모든 것보다 시간이 오래 걸릴 수 있습니다.

SO 관련 질문 :

트랜잭션이 도중에 DB 행에 대한 잠금을 수집하기 때문에 매우 길고 오래 실행되는 쿼리 의 전환점이있을 수 있습니다 . 매우 큰 쿼리는 오랜 시간 동안 많은 잠금을 유지하여 동시 쿼리충돌을 일으킬 수 있습니다 .


답변