[mysql] 쿼리 대 여러 쿼리

JOIN 쿼리가 여러 쿼리보다 빠릅니까? 기본 쿼리를 실행 한 다음 기본 쿼리의 결과를 기반으로 다른 많은 SELECT를 실행합니다.

가입하면 응용 프로그램의 디자인이 많이 복잡해지기 때문에 묻습니다.

그들이 더 빠르면 누구나 대략적으로 대략적으로 얼마만큼을 근사 할 수 있습니까? 1.5x이면 상관하지 않지만 10x이면 내가 생각합니다.



답변

특정 사례와 관련된 답변을 제공하기에는 너무 모호합니다. 그것은 많은 것들에 달려 있습니다. Jeff Atwood (이 사이트의 창립자)는 실제로 이것에 대해 썼습니다 . 대부분의 경우 올바른 인덱스가 있고 JOIN을 올바르게 수행하면 일반적으로 여러 번보다 1 회 트립하는 것이 더 빠릅니다.


답변

내부 조인의 경우 일치하는 행만 가져 오기 때문에 단일 쿼리가 적합합니다. 왼쪽 조인의 경우 여러 쿼리가 훨씬 낫습니다 … 다음 벤치 마크를 살펴보십시오.

  1. 5 개의 조인이있는 단일 쿼리

    쿼리 : 8.074508 초

    결과 크기 : 2268000

  2. 연속으로 5 개의 쿼리

    결합 된 쿼리 시간 : 0.00262 초

    결과 크기 : 165 (6 + 50 + 7 + 12 + 90)

.

두 경우 모두 동일한 결과를 얻습니다 (6 x 50 x 7 x 12 x 90 = 2268000).

왼쪽 조인은 중복 데이터와 함께 기하 급수적으로 더 많은 메모리를 사용합니다.

두 테이블의 조인 만 수행하는 것이 아니라 일반적으로 3 개 이상이고 다른 쿼리의 가치가있는 경우 메모리 제한은 나쁘지 않을 수 있습니다.

참고로 MySQL 서버는 내 응용 프로그램 서버 바로 옆에 있으므로 연결 시간을 무시할 수 있습니다. 연결 시간이 초 단위라면 이점이있을 수 있습니다.

솔직한


답변

이 질문은 오래되었지만 일부 벤치 마크가 누락되었습니다. 나는 두 경쟁자에 대해 JOIN을 벤치마킹했습니다.

  • N + 1 쿼리
  • (2 개) 질의하는 사용 번째 WHERE IN(...)또는 동등한

그 결과는 분명하다 : MySQL을, JOIN이다 훨씬 더 빨리. N + 1 쿼리는 응용 프로그램의 성능을 크게 떨어 뜨릴 수 있습니다.

N + 1 vs WHERE IN 가입

즉, 매우 적은 수의 별개의 외부 레코드를 가리키는 많은 레코드를 선택하지 않는 한. 극단적 인 경우에 대한 벤치 마크는 다음과 같습니다.

JOIN vs N + 1-동일한 외래 레코드를 가리키는 모든 레코드

대다 관계를 조인하지 않으면 외래 키가 다른 테이블에 있고 주 테이블 데이터를 여러 번 복제하지 않는 한 일반적인 응용 프로그램에서 발생할 가능성이 거의 없습니다.

테이크 아웃 :

  • * 대일 관계의 경우 항상 JOIN
  • * 대다 관계의 경우 두 번째 쿼리 더 빠를 있습니다.

자세한 내용은 Medium에 대한 내 기사 를 참조하십시오.


답변

나는 실제로이 질문에 답을 찾고, 주어진 답변을 읽은 후에 DB 쿼리 성능을 비교하는 가장 좋은 방법은 고려할 변수가 많기 때문에 실제 숫자를 얻는 것에 만 동의 할 수 있습니다 그러나 나는 그들 사이의 숫자를 비교하면 거의 모든 경우에 좋지 않다고 생각합니다. 내 말은 숫자는 항상 허용되는 숫자와 비교해야하며 서로 확실히 비교해서는 안된다는 것입니다.

쿼리하는 한 가지 방법으로 0.02 초가 걸리고 다른 한 가지 방법으로 20 초가 걸리는 것을 이해하면 큰 차이가 있습니다. 그러나 한 쿼리 방법에 0.0000000002 초가 걸리고 다른 방법에 0.0000002 초가 걸리면 어떻게해야합니까? 두 경우 모두 하나의 방법은 무려 1000 배 빠른 다른 하나보다,하지만은 정말 두 번째 경우에 “무려”아직?

내가 개인적으로 본 결론 : 실적이 좋으면 쉬운 해결책을 찾으십시오.


답변

50,000 행 테이블에서 하나의 행을 선택하고 100,000 행 테이블에서 하나의 행과 조인하는 빠른 테스트를 수행했습니다. 기본적으로 다음과 같습니다.

$id = mt_rand(1, 50000);
$row = $db->fetchOne("SELECT * FROM table1 WHERE id = " . $id);
$row = $db->fetchOne("SELECT * FROM table2 WHERE other_id = " . $row['other_id']);

vs

$id = mt_rand(1, 50000);
$db->fetchOne("SELECT table1.*, table2.*
    FROM table1
    LEFT JOIN table1.other_id = table2.other_id
    WHERE table1.id = " . $id);

두 가지 선택 방법은 50,000 읽기에 3.7 초가 걸렸지 만 집에서 느린 컴퓨터에서는 JOIN이 2.0 초에 걸렸습니다. INNER JOIN과 LEFT JOIN은 차이가 없었습니다. 여러 행을 가져 오면 (예 : IN SET 사용) 비슷한 결과가 나타납니다.


답변

실제 질문은 다음 같습니다. 이 레코드는 일대일 관계 또는 일대 다 관계 입니까?

TLDR 답변 :

일대일 인 경우, JOIN명세서를 사용하십시오 .

일대 SELECT다인 경우 서버 측 코드 최적화와 함께 하나 이상의 명령문을 사용하십시오.

최적화를 위해 SELECT를 사용하는 이유와 방법

SELECT일대 다 관계를 기반으로하는 대규모 레코드 그룹에서 ‘조인 대신 여러 쿼리를 사용 JOIN‘ 하면 ‘지수 적으로 메모리 누수 문제가 발생 하므로 최적의 효율성을 얻을 수 있습니다. 모든 데이터를 가져온 다음 서버 측 스크립팅 언어를 사용하여 정렬하십시오.

SELECT * FROM Address WHERE Personid IN(1,2,3);

결과 :

Address.id : 1            // First person and their address
Address.Personid : 1
Address.City : "Boston"

Address.id : 2            // First person's second address
Address.Personid : 1
Address.City : "New York"

Address.id : 3            // Second person's address
Address.Personid : 2
Address.City : "Barcelona"

여기서는 하나의 select 문에서 모든 레코드를 가져옵니다. 이것은 JOIN다른 쿼리의 하위 구성 요소로 한 번에 하나씩 작은 그룹의 레코드를 가져 오는 것 보다 낫습니다 . 그런 다음 서버 측 코드로 구문 분석합니다 …

<?php
    foreach($addresses as $address) {
         $persons[$address['Personid']]->Address[] = $address;
    }
?>

최적화에 JOIN을 사용하지 않을 경우

JOIN하나의 단일 레코드와 일대일 관계를 기반으로 한 큰 레코드 그룹을 작성하면 여러 SELECT명령문에 비해 최적의 효율성을 얻을 수 있으며 이는 단순히 다음 레코드 유형을 가져옵니다.

그러나 JOIN일대 다 관계로 레코드를 가져올 때 비효율적입니다.

예 : 데이터베이스 블로그에는 3 개의 관심 테이블 (블로그 포스트, 태그 및 주석)이 있습니다.

SELECT * from BlogPost
LEFT JOIN Tag ON Tag.BlogPostid = BlogPost.id
LEFT JOIN Comment ON Comment.BlogPostid = BlogPost.id;

블로그 게시물 1 개, 태그 2 개, 댓글 2 개가 있으면 다음과 같은 결과가 나타납니다.

Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag2, comment1,
Row4: tag2, comment2,

각 레코드가 어떻게 복제되는지 확인하십시오. 좋아요, 2 개의 댓글과 2 개의 태그는 4 행입니다. 댓글 4 개와 태그 4 개가 있으면 어떻게 되나요? 당신은 8 개의 줄을 얻지 못합니다-당신은 16 개의 줄을 얻습니다 :

Row1: tag1, comment1,
Row2: tag1, comment2,
Row3: tag1, comment3,
Row4: tag1, comment4,
Row5: tag2, comment1,
Row6: tag2, comment2,
Row7: tag2, comment3,
Row8: tag2, comment4,
Row9: tag3, comment1,
Row10: tag3, comment2,
Row11: tag3, comment3,
Row12: tag3, comment4,
Row13: tag4, comment1,
Row14: tag4, comment2,
Row15: tag4, comment3,
Row16: tag4, comment4,

더 많은 테이블, 더 많은 레코드 등을 추가하면 문제는 대부분 중복 데이터로 가득 찬 수백 개의 행으로 빠르게 팽창합니다 .

이 중복 비용은 얼마입니까? 메모리 (SQL 서버 및 중복 제거를 시도하는 코드) 및 네트워킹 리소스 (SQL 서버와 코드 서버 간)

출처 : https://dev.mysql.com/doc/refman/8.0/en/nested-join-optimization.html ; https://dev.mysql.com/doc/workbench/en/wb-relationship-tools.html


답변

별도의 쿼리와 조인을 모두 구성한 다음 각각의 시간을 정하십시오. 실제 숫자보다 큰 도움은 없습니다.

더 나은 방법은 각 쿼리의 시작 부분에 “EXPLAIN”을 추가하는 것입니다. 이것은 MySQL이 데이터 요청에 응답하기 위해 사용하는 서브 쿼리 수와 각 쿼리에 대해 스캔 된 행 수를 알려줍니다.