복붙노트

[SQL] 하위 쿼리 대 가입

SQL

하위 쿼리 대 가입

나는 구식 MySQL 사용자이고 항상 하위 쿼리를 통해 가입 선호했다. 그러나 요즘은 모두가 하위 쿼리를 사용하고, 나는 그것을 싫어; 난 이유를 모르겠어.

어떤 차이가 있는지 나 자신에 대한 판단에 대한 이론적 지식이 부족합니다. A는 가입 때문에 걱정에이 아무것도에 대해 없기 때문에 좋은으로 하위 쿼리인가?

해결법

  1. ==============================

    1.MySQL의 설명서에서 촬영 (13.2.10.11 재 작성 하위 쿼리는 조인으로) :

    MySQL의 설명서에서 촬영 (13.2.10.11 재 작성 하위 쿼리는 조인으로) :

    하위 쿼리가 느린 할 수 있도록 LEFT [OUTER]을 가입하지만, 내 생각에 그 강도는 약간 높은 가독성보다.

  2. ==============================

    2.하위 쿼리 형태의 문제를 해결하기 위해 논리적으로 올바른 방법입니다, "A로부터 B에서 사실에 조건부 사실을 얻으십시오". 이러한 경우, 그것은 조인을 수행하는 것보다 서브 쿼리 스틱 B에 더 논리적 의미가 있습니다. 그것은 당신이 때문에 나에 대한 여러 경기에에서 중복 사실을 얻기에 관하여주의 할 필요가 없기 때문에, 실질적인 의미에서, 또한 안전

    하위 쿼리 형태의 문제를 해결하기 위해 논리적으로 올바른 방법입니다, "A로부터 B에서 사실에 조건부 사실을 얻으십시오". 이러한 경우, 그것은 조인을 수행하는 것보다 서브 쿼리 스틱 B에 더 논리적 의미가 있습니다. 그것은 당신이 때문에 나에 대한 여러 경기에에서 중복 사실을 얻기에 관하여주의 할 필요가 없기 때문에, 실질적인 의미에서, 또한 안전

    실질적으로 말해서, 그러나, 대답은 일반적으로 성능까지 제공됩니다. A는 하위 쿼리 대에 가입 주어 졌을 때 일부 optimisers 레몬을 빨아, 일부는 레몬에게 다른 방법을 빨아, 이것은 최적화 별, DBMS 버전 별 및 쿼리 다릅니다.

    역사적으로, 명시 적 보통이다 더 나은 조인하지만 optimisers 더 나은 모든 시간을 받고, 나는 다음 구조 조정을 논리적으로 일관성있는 방법으로 첫째 쓰기 쿼리에 선호하고, 그래서 성능 제약이 보증하는 경우에 따라서 설립 지혜를 승리 조인.

  3. ==============================

    3.대부분의 경우 조인 빠른 서브 쿼리보다 및 하위 쿼리가 빠를하는 것은 매우 드문 일이다.

    대부분의 경우 조인 빠른 서브 쿼리보다 및 하위 쿼리가 빠를하는 것은 매우 드문 일이다.

    에서는 RDBMS가 더 나은 쿼리 인 실행 계획을 만들 수 있으며 모든 쿼리를 실행하고 처리 할 모든 데이터를로드 하위 쿼리는 달리, 데이터를 처리 할 수로드되어야 하는지를 예측하고 시간을 절약 할 수 있습니다 조인 .

    하위 쿼리에 좋은 것은 그들이 조인보다 더 많은 읽을 수 있다는 것입니다 :의 이유는 대부분의 새로운 SQL 사람들이 그들을 선호; 그것은 쉬운 방법입니다; 이 성능에 관해서는하지만, 그들도 읽기 어려운 일이 아니다 비록 있습니다 더 나은 대부분의 경우에 합류했다.

  4. ==============================

    4.사용하여 데이터베이스의 데이터에 대한 쿼리를 실행하는 방법을 참조 설명한다. 이 답변에 "이 달려있다"거대한가 ...

    사용하여 데이터베이스의 데이터에 대한 쿼리를 실행하는 방법을 참조 설명한다. 이 답변에 "이 달려있다"거대한가 ...

    조인에 PostgreSQL은 하위 쿼리를 다시 작성할 수 있습니다 또는 한 빨리 다른 것보다 생각하는 경우는 하위 쿼리에 가입 할 수 있습니다. 그것은 모든 등 데이터, 인덱스, 상관 관계, 데이터의 양, 쿼리에 따라 달라집니다

  5. ==============================

    5.2010 년에, 나는이 질문의 저자에 합류했을 강하게 가입을 위해 투표했을 것이다. 그러나 (특히 MySQL은) 더 많은 경험을 나는 명시 할 수 있습니다 : 예 하위 쿼리가 더 좋을 수 있습니다. 여기에 여러 답변을 읽었습니다. 일부는 서브 쿼리가 더 빨리, 진술, 그러나 그것은 좋은 설명이 부족. 나는이 (매우) 늦게 대답 하나를 제공 할 수 있기를 바랍니다 :

    2010 년에, 나는이 질문의 저자에 합류했을 강하게 가입을 위해 투표했을 것이다. 그러나 (특히 MySQL은) 더 많은 경험을 나는 명시 할 수 있습니다 : 예 하위 쿼리가 더 좋을 수 있습니다. 여기에 여러 답변을 읽었습니다. 일부는 서브 쿼리가 더 빨리, 진술, 그러나 그것은 좋은 설명이 부족. 나는이 (매우) 늦게 대답 하나를 제공 할 수 있기를 바랍니다 :

    하위 쿼리의 다른 형태가있다 : 첫째, 나에게 가장 중요한 말을하자

    그리고 두 번째로 중요한 문 : 크기 문제

    당신이 하위 쿼리를 사용하는 경우 DB-Server가 하위 쿼리를 실행하는 방법, 당신은 알고 있어야합니다. 특히 하위 쿼리가 한 번 또는 모든 행에 대해 평가하는 경우! 다른 측면에서, 현대 DB-Server는 많은 최적화 할 수 있습니다. 어떤 경우에는 하위 쿼리는 쿼리를 최적화하는 데 도움이 있지만, DB-서버의 최신 버전은 최적화가되지 않는 만들 수 있습니다.

    SELECT moo, (SELECT roger FROM wilco WHERE moo = me) AS bar FROM foo
    

    하위 쿼리가 foo는에서 모든 결과 행에 대해 실행되어 있는지 알고 있어야합니다. 가능하면이를 방지, 그것은 크게 거대한 데이터 세트에 쿼리를 속도가 느려질 수 있습니다. 하위 쿼리 푸에 대한 참조가없는 경우, 그것은 정적 컨텐츠와 DB 서버에 의해 최적화 할 수 있으며, 한 번만 평가 될 수있다.

    SELECT moo FROM foo WHERE bar = (SELECT roger FROM wilco WHERE moo = me)
    

    당신이 운이 경우, DB는 내부적으로 가입이 점을 최적화합니다. 그렇지 않은 경우는 단지 결과 선택 형처럼, foo는의 모든 행에 대해 하위 쿼리를 실행하기 때문에, 쿼리는 거대한 데이터 세트에 매우, 매우 느리게 될 것입니다.

    SELECT moo, bar 
      FROM foo 
        LEFT JOIN (
          SELECT MIN(bar), me FROM wilco GROUP BY me
        ) ON moo = me
    

    이것은 흥미 롭다. 우리는 결합 하위 쿼리에 가입하세요. 그리고 여기에 우리가 하위 쿼리의 진정한 힘을 얻을. 윌코의 행 수백만 그러나 약간 별개 나와 함께 데이터 집합을 상상해보십시오. 대신 큰 테이블에 대해 가입, 우리는 지금에 가입하는 작은 임시 테이블을 가지고있다. 이 훨씬 빠르게 데이터베이스 크기에 따라 쿼리에서 발생할 수 있습니다. 당신은 임시 테이블을 CREATE와 같은 효과를 가질 수 있습니다 ... 그리고 INSERT INTO는 ... SELECT는 ... 매우 복잡한 쿼리에 더 나은 가독성을 제공 할 수 있습니다 (하지만 반복 읽기 분리 레벨에서 데이터 세트를 잠글 수)있다.

    SELECT moo, bar
      FROM (
        SELECT moo, CONCAT(roger, wilco) AS bar
          FROM foo
          GROUP BY moo
          HAVING bar LIKE 'SpaceQ%'
      ) AS temp_foo
      ORDER BY bar
    

    여러 수준의 중첩 하위 쿼리를 할 수 있습니다. 당신이 그룹 또는 정렬 결과를 가지고있을 때, 거대한 데이터 세트에 도움이 될 수 있습니다. 일반적으로 DB-Server는이에 대한 임시 테이블을 생성하지만 때로는 당신은 단지 결과 집합에, 전체 테이블에 정렬이 필요하지 않습니다. 이 테이블의 크기에 따라 훨씬 더 나은 성능을 제공 할 수 있습니다.

    하위 쿼리는 조인에 대한 대체하지 않습니다 그리고 당신은 (가능하지만) 이런 식으로 사용하지합니다. 내 소견에서, 서브 쿼리의 올바른 사용이 임시 테이블을 CREATE의 빠른 교체로 사용하는 것입니다 있습니다 .... 좋은 서브 쿼리 방식으로 데이터 집합을 줄여, 당신은이 가입의 ON 문에서 수행 할 수 없습니다 . 하위 쿼리가 키워드 GROUP BY 또는 DISTINCT 중 하나를 가지고 있으며, 바람직하게는 선택 필드 또는 문에 위치하지 않은 경우, 그것은 성능을 많이 향상시킬 수 있습니다.

  6. ==============================

    6.우선, 두 먼저에 하위 쿼리와 쿼리를 구별해야한다 비교 :

    우선, 두 먼저에 하위 쿼리와 쿼리를 구별해야한다 비교 :

    해당 같은 RDBMS가 볼 수있는 좋은 조인 쿼리 및 하위 쿼리의 첫 번째 클래스와 동일한 쿼리 계획을 생성합니다.

    요즘은 심지어 MySQL은 그 작업을 수행합니다.

    그러나 때때로 그렇지 않습니다, 그러나 이것은 항상 이길 것이다 조인 것을 의미하지 않는다 - MySQL의 성능 향상에 하위 쿼리를 사용할 때이 사건이 있었다. (예를 들어 제대로 비용을 추정하는 것을 방지 MySQL의 계획이있는 경우와 플래너가 같은 다음 하위 쿼리와 조인 변형 및 하위 쿼리-변형 능가 할 수 표시하지 않는 경우 특정 경로를 강제로 조인).

    결론은 모두가 참여하고 하나가 더 잘 수행 할 확인하려면 하위 쿼리가 변형에 대한 당신의 쿼리를 테스트해야한다는 것입니다.

    두 번째 클래스의 비교는 그 쿼리를 사용하여 다시 작성 될 수 없기 때문에 아무 의미가 하위 쿼리가 필요한 작업을 수행하는 자연적인 방법이며, 당신이 그들을 차별하지 말아야 조인 이러한 경우하지 않습니다.

  7. ==============================

    7.SQL Server에 대한 MSDN 문서를 말한다

    SQL Server에 대한 MSDN 문서를 말한다

    그래서 당신은 뭔가를해야하는 경우

    select * from t1 where exists select * from t2 where t2.parent=t1.id
    

    대신 조인을 사용하려고합니다. 다른 경우에는, 그 차이는 없습니다.

    내가 말할 : 하위 쿼리에 대한 생성 기능 cluttter의 문제를 제거하고 하위 쿼리에 추가 논리를 구현할 수 있습니다. 나는 가능하면 하위 쿼리에 대한 기능을 작성하는 것이 좋습니다 그래서.

    코드의 혼란은 큰 문제이며, 업계는 수십 년 동안 그것을 방지에 노력하고있다.

  8. ==============================

    8.나는 특정 (사용)의 경우에서 발생할 수있는 중복과 문제가 결과의 문제는 아래-강조 인용 답변에 있었던 것을 생각한다.

    나는 특정 (사용)의 경우에서 발생할 수있는 중복과 문제가 결과의 문제는 아래-강조 인용 답변에 있었던 것을 생각한다.

    (마르셀로 칸토이는하지만 그것을 언급)

    나는 SQL에 스탠포드의 Lagunita 과정의 예를 인용합니다.

    +------+--------+------+--------+
    | sID  | sName  | GPA  | sizeHS |
    +------+--------+------+--------+
    |  123 | Amy    |  3.9 |   1000 |
    |  234 | Bob    |  3.6 |   1500 |
    |  345 | Craig  |  3.5 |    500 |
    |  456 | Doris  |  3.9 |   1000 |
    |  567 | Edward |  2.9 |   2000 |
    |  678 | Fay    |  3.8 |    200 |
    |  789 | Gary   |  3.4 |    800 |
    |  987 | Helen  |  3.7 |    800 |
    |  876 | Irene  |  3.9 |    400 |
    |  765 | Jay    |  2.9 |   1500 |
    |  654 | Amy    |  3.9 |   1000 |
    |  543 | Craig  |  3.4 |   2000 |
    +------+--------+------+--------+
    

    (응용 프로그램은 특정 대학과 전공에 만든)

    +------+----------+----------------+----------+
    | sID  | cName    | major          | decision |
    +------+----------+----------------+----------+
    |  123 | Stanford | CS             | Y        |
    |  123 | Stanford | EE             | N        |
    |  123 | Berkeley | CS             | Y        |
    |  123 | Cornell  | EE             | Y        |
    |  234 | Berkeley | biology        | N        |
    |  345 | MIT      | bioengineering | Y        |
    |  345 | Cornell  | bioengineering | N        |
    |  345 | Cornell  | CS             | Y        |
    |  345 | Cornell  | EE             | N        |
    |  678 | Stanford | history        | Y        |
    |  987 | Stanford | CS             | Y        |
    |  987 | Berkeley | CS             | Y        |
    |  876 | Stanford | CS             | N        |
    |  876 | MIT      | biology        | Y        |
    |  876 | MIT      | marine biology | N        |
    |  765 | Stanford | history        | Y        |
    |  765 | Cornell  | history        | N        |
    |  765 | Cornell  | psychology     | Y        |
    |  543 | MIT      | CS             | N        |
    +------+----------+----------------+----------+
    

    의가 (에 관계없이 대학) CS 전공 신청 한 학생의 GPA 점수를 찾아 봅시다

    하위 쿼리를 사용 :

    select GPA from Student where sID in (select sID from Apply where major = 'CS');
    
    +------+
    | GPA  |
    +------+
    |  3.9 |
    |  3.5 |
    |  3.7 |
    |  3.9 |
    |  3.4 |
    +------+
    

    이 결과 집합에 대한 평균 값은 다음과 같습니다

    select avg(GPA) from Student where sID in (select sID from Apply where major = 'CS');
    
    +--------------------+
    | avg(GPA)           |
    +--------------------+
    | 3.6800000000000006 |
    +--------------------+
    

    사용하여 가입 :

    select GPA from Student, Apply where Student.sID = Apply.sID and Apply.major = 'CS';
    
    +------+
    | GPA  |
    +------+
    |  3.9 |
    |  3.9 |
    |  3.5 |
    |  3.7 |
    |  3.7 |
    |  3.9 |
    |  3.4 |
    +------+
    

    이 결과 집합에 대한 평균 값 :

    select avg(GPA) from Student, Apply where Student.sID = Apply.sID and Apply.major = 'CS';
    
    +-------------------+
    | avg(GPA)          |
    +-------------------+
    | 3.714285714285714 |
    +-------------------+
    

    우리의 사용 사례에 결과를 오해의 소지가 두 번째 시도 수율, 그것은 평균값의 계산을 위해 중복 계산 주어진 것은 분명하다. 기반 문이 잘못 3.9 점수의 세 가지 사건 중 하나를 유지할 주어진 문제를 제거하지 않습니다 - 조인과 별개의 사용이 것 또한 분명하다. 올바른 경우는 3.9 두 (2) 발생이 우리가 실제로 우리의 쿼리 기준을 준수하는 점수를 두 (2) 학생들이 주어진 점수에 대한 계정입니다.

    어떤 경우에는 하위 쿼리 성능 문제 외에, 갈 수있는 가장 안전한 방법 것 같다.

  9. ==============================

    9.오래된 맘보 CMS에서 매우 큰 데이터베이스에서 실행 :

    오래된 맘보 CMS에서 매우 큰 데이터베이스에서 실행 :

    SELECT id, alias
    FROM
      mos_categories
    WHERE
      id IN (
        SELECT
          DISTINCT catid
        FROM mos_content
      );
    

    0초

    SELECT
      DISTINCT mos_content.catid,
      mos_categories.alias
    FROM
      mos_content, mos_categories
    WHERE
      mos_content.catid = mos_categories.id;
    

    ~ 삼초

    은 행의 숫자를 정확하게 검사 할 것을 쇼를 EXPLAIN, 그러나 사람은 3 초 소요 하나는 근처의 순간이다. 이야기의 교훈? (그것이없는 경우?) 성능이 중요하다면, 그것은 여러 가지 방법을 시도하고 하나가 빠르게되는 참조하십시오.

    과...

    SELECT
      DISTINCT mos_categories.id,
      mos_categories.alias
    FROM
      mos_content, mos_categories
    WHERE
      mos_content.catid = mos_categories.id;
    

    0초

    또, 같은 결과는 행의 같은 수를 조사했다. 내 생각 엔 DISTINCT mos_content.catid가 DISTINCT mos_categories.id가보다 알아 내기 위해 훨씬 오래 걸린다는 것이다.

  10. ==============================

    10.테이블이 다음 미만 10 만 개 기록이있는 경우 이가지 경우처럼 내 관찰 당으로, 빠르게 작동합니다 가입 할 수 있습니다.

    테이블이 다음 미만 10 만 개 기록이있는 경우 이가지 경우처럼 내 관찰 당으로, 빠르게 작동합니다 가입 할 수 있습니다.

    그러나 테이블이 다음 10 만 개 이상의 레코드가있는 경우 하위 쿼리는 최고의 결과입니다.

    나는 쿼리 아래에 만들어지고 그 결과 시간이 같다고에서 50 만 개 레코드가 하나 개의 테이블을 가지고

    SELECT * 
    FROM crv.workorder_details wd 
    inner join  crv.workorder wr on wr.workorder_id = wd.workorder_id;
    
    select * 
    from crv.workorder_details 
    where workorder_id in (select workorder_id from crv.workorder)
    
  11. ==============================

    11.그들은 IN 키워드를 복수 행에 대하여 값을 비교하는데 이용 될 수 있지만 서브 쿼리는 일반적으로 원자 값으로서 하나의 행을 리턴하는 데 사용된다. 그들은 WHERE 절 등, 대상 목록을 포함하여 SQL 문에 거의 모든 의미있는 지점에서 사용할 수 있습니다. 간단한 하위 쿼리는 검색 조건으로 사용 할 수있다. 예를 들어, 테이블의 쌍 사이 :

    그들은 IN 키워드를 복수 행에 대하여 값을 비교하는데 이용 될 수 있지만 서브 쿼리는 일반적으로 원자 값으로서 하나의 행을 리턴하는 데 사용된다. 그들은 WHERE 절 등, 대상 목록을 포함하여 SQL 문에 거의 모든 의미있는 지점에서 사용할 수 있습니다. 간단한 하위 쿼리는 검색 조건으로 사용 할 수있다. 예를 들어, 테이블의 쌍 사이 :

       SELECT title FROM books WHERE author_id = (SELECT id FROM authors WHERE last_name = 'Bar' AND first_name = 'Foo');
    

    서브 쿼리의 결과에 정상적인 값 연산자를 사용하여 하나 개의 필드를 반환해야해야합니다. 당신은 다른 값을 사용 IN 세트 내에서 단일 값의 존재 확인에 관심이있는 경우 :

       SELECT title FROM books WHERE author_id IN (SELECT id FROM authors WHERE last_name ~ '^[A-E]');
    

    이 말 왼쪽 가입 그냥 테이블 A와 B 조인 조건이 경우에도 테이블 B에 일치하는 기록을 찾을 수없는에서 물건을 가입 할 위치 등에서 분명히 다르다

    당신은 단지 속도에 대해 걱정하는 경우 당신은 당신의 데이터베이스를 확인하고 좋은 쿼리를 작성 및 성능에 상당한 차이가 있는지해야합니다.

  12. ==============================

    12.MySQL 버전 : 5.5.28-0ubuntu0.12.04.2 로그

    MySQL 버전 : 5.5.28-0ubuntu0.12.04.2 로그

    나는 항상 더 나은 MySQL은 서브 쿼리보다 가입하지만, 판단을 할 수있는 더 좋은 방법입니다 EXPLAIN 인상도했다. 여기에 서브 쿼리가 더 나은 조인보다 작업 예입니다.

    여기에 3 서브 쿼리 내 쿼리는 다음과 같습니다

    EXPLAIN SELECT vrl.list_id,vrl.ontology_id,vrl.position,l.name AS list_name, vrlih.position AS previous_position, vrl.moved_date 
    FROM `vote-ranked-listory` vrl 
    INNER JOIN lists l ON l.list_id = vrl.list_id 
    INNER JOIN `vote-ranked-list-item-history` vrlih ON vrl.list_id = vrlih.list_id AND vrl.ontology_id=vrlih.ontology_id AND vrlih.type='PREVIOUS_POSITION' 
    INNER JOIN list_burial_state lbs ON lbs.list_id = vrl.list_id AND lbs.burial_score < 0.5 
    WHERE vrl.position <= 15 AND l.status='ACTIVE' AND l.is_public=1 AND vrl.ontology_id < 1000000000 
     AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=43) IS NULL 
     AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=55) IS NULL 
     AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=246403) IS NOT NULL 
    ORDER BY vrl.moved_date DESC LIMIT 200;
    

    쇼를 EXPLAIN :

    +----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
    | id | select_type        | table    | type   | possible_keys                                       | key          | key_len | ref                                             | rows | Extra                    |
    +----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
    |  1 | PRIMARY            | vrl      | index  | PRIMARY                                             | moved_date   | 8       | NULL                                            |  200 | Using where              |
    |  1 | PRIMARY            | l        | eq_ref | PRIMARY,status,ispublic,idx_lookup,is_public_status | PRIMARY      | 4       | ranker.vrl.list_id                              |    1 | Using where              |
    |  1 | PRIMARY            | vrlih    | eq_ref | PRIMARY                                             | PRIMARY      | 9       | ranker.vrl.list_id,ranker.vrl.ontology_id,const |    1 | Using where              |
    |  1 | PRIMARY            | lbs      | eq_ref | PRIMARY,idx_list_burial_state,burial_score          | PRIMARY      | 4       | ranker.vrl.list_id                              |    1 | Using where              |
    |  4 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
    |  3 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
    |  2 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
    +----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
    

    함께 조인 같은 쿼리는 다음과 같습니다

    EXPLAIN SELECT vrl.list_id,vrl.ontology_id,vrl.position,l.name AS list_name, vrlih.position AS previous_position, vrl.moved_date 
    FROM `vote-ranked-listory` vrl 
    INNER JOIN lists l ON l.list_id = vrl.list_id 
    INNER JOIN `vote-ranked-list-item-history` vrlih ON vrl.list_id = vrlih.list_id AND vrl.ontology_id=vrlih.ontology_id AND vrlih.type='PREVIOUS_POSITION' 
    INNER JOIN list_burial_state lbs ON lbs.list_id = vrl.list_id AND lbs.burial_score < 0.5 
    LEFT JOIN list_tag lt1 ON lt1.list_id = vrl.list_id AND lt1.tag_id = 43 
    LEFT JOIN list_tag lt2 ON lt2.list_id = vrl.list_id AND lt2.tag_id = 55 
    INNER JOIN list_tag lt3 ON lt3.list_id = vrl.list_id AND lt3.tag_id = 246403 
    WHERE vrl.position <= 15 AND l.status='ACTIVE' AND l.is_public=1 AND vrl.ontology_id < 1000000000 
    AND lt1.list_id IS NULL AND lt2.tag_id IS NULL 
    ORDER BY vrl.moved_date DESC LIMIT 200;
    

    출력은 :

    +----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
    | id | select_type | table | type   | possible_keys                                       | key          | key_len | ref                                         | rows | Extra                                        |
    +----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
    |  1 | SIMPLE      | lt3   | ref    | list_tag_key,list_id,tag_id                         | tag_id       | 5       | const                                       | 2386 | Using where; Using temporary; Using filesort |
    |  1 | SIMPLE      | l     | eq_ref | PRIMARY,status,ispublic,idx_lookup,is_public_status | PRIMARY      | 4       | ranker.lt3.list_id                          |    1 | Using where                                  |
    |  1 | SIMPLE      | vrlih | ref    | PRIMARY                                             | PRIMARY      | 4       | ranker.lt3.list_id                          |  103 | Using where                                  |
    |  1 | SIMPLE      | vrl   | ref    | PRIMARY                                             | PRIMARY      | 8       | ranker.lt3.list_id,ranker.vrlih.ontology_id |   65 | Using where                                  |
    |  1 | SIMPLE      | lt1   | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.lt3.list_id,const                    |    1 | Using where; Using index; Not exists         |
    |  1 | SIMPLE      | lbs   | eq_ref | PRIMARY,idx_list_burial_state,burial_score          | PRIMARY      | 4       | ranker.vrl.list_id                          |    1 | Using where                                  |
    |  1 | SIMPLE      | lt2   | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.lt3.list_id,const                    |    1 | Using where; Using index                     |
    +----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
    

    행 컬럼의 비교는 차이 및 임시 사용 사용하는 조인 쿼리를 말한다; filesort를 사용.

    물론 나는 모두에게 쿼리를 실행할 때, 첫 번째는 0.02 초에서 수행되고, 두 번째는, 그래서 제대로 이러한 쿼리를 설명 EXPLAIN도 1 분 후에 완료되지 않습니다.

    나는 INNER이없는 경우 즉, I 삭제 경우 list_tag 테이블에 가입하세요

    AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=246403) IS NOT NULL  
    

    대응 첫 번째 쿼리와에서 :

    INNER JOIN list_tag lt3 ON lt3.list_id = vrl.list_id AND lt3.tag_id = 246403
    

    두 번째 쿼리에서 다음 두 쿼리와 이러한 쿼리 모두 같은 수의 행이 동등 빠른 실행 수익률을 설명한다.

  13. ==============================

    13.하위 쿼리는 실시간으로 집계 함수를 계산하는 능력을 가지고있다. 예를 들면 책의 최소 가격을 찾아이 가격으로 판매되는 모든 책을 얻을. 1) 서브 쿼리를 사용 :

    하위 쿼리는 실시간으로 집계 함수를 계산하는 능력을 가지고있다. 예를 들면 책의 최소 가격을 찾아이 가격으로 판매되는 모든 책을 얻을. 1) 서브 쿼리를 사용 :

    SELECT titles, price
    FROM Books, Orders
    WHERE price = 
    (SELECT MIN(price)
     FROM Orders) AND (Books.ID=Orders.ID);
    

    2) 사용 조인

    SELECT MIN(price)
         FROM Orders;
    -----------------
    2.99
    
    SELECT titles, price
    FROM Books b
    INNER JOIN  Orders o
    ON b.ID = o.ID
    WHERE o.price = 2.99;
    
  14. ==============================

    14.어떤 사람들은 ". 그것은 한 빨리 다른 것보다 생각하는 경우 가입에 일부 RDBMS는 하위 쿼리를 다시 작성할 수 있습니다 또는 하위 쿼리에 가입"말을하지만,이 문은 하위 쿼리와 복잡한 쿼리하지 확실히, 간단한 경우에 적용되는 실제 원인 성능 문제.

    어떤 사람들은 ". 그것은 한 빨리 다른 것보다 생각하는 경우 가입에 일부 RDBMS는 하위 쿼리를 다시 작성할 수 있습니다 또는 하위 쿼리에 가입"말을하지만,이 문은 하위 쿼리와 복잡한 쿼리하지 확실히, 간단한 경우에 적용되는 실제 원인 성능 문제.

  15. ==============================

    15.제 합류 테이블 기본 테이블보다 훨씬 더 많은 데이터를 가질 때의 차이만을 볼 수있다. 나는 다음과 같은 경험을했다 ...

    제 합류 테이블 기본 테이블보다 훨씬 더 많은 데이터를 가질 때의 차이만을 볼 수있다. 나는 다음과 같은 경험을했다 ...

    우리는 3 개 십만 항목에 대해 십만 항목과 회원 데이터 (우정)의 사용자 테이블을했다. 그것은 친구와 자신의 데이터를 취하기 위해 문을 가입하지만 큰 지연이었다. 그러나 회원 테이블에 적은 양의 데이터가 있었다 잘 작동했다. 우리는 하위 쿼리를 사용하도록 변경되면 그것을 잘 일했다.

    그러나 그 동안의 쿼리는 기본 테이블보다 적은 수의 항목이 다른 테이블로 작업에 참여.

    내가 생각하는 그래서 조인과 서브 쿼리 문이 잘 작동하고이 데이터와 상황에 따라 달라집니다.

  16. ==============================

    16.요즘은 많은 DBS는 서브 쿼리를 최적화하고 결합 할 수 있습니다. 따라서, 당신은 단지 설명하고 하나가 빠르게 확인할 사용하여 쿼리를 검사 gotto. 성능에 큰 차이가없는 경우가 간단하고 이해하기 쉽게, 나는이 사용하는 하위 쿼리를 선호합니다.

    요즘은 많은 DBS는 서브 쿼리를 최적화하고 결합 할 수 있습니다. 따라서, 당신은 단지 설명하고 하나가 빠르게 확인할 사용하여 쿼리를 검사 gotto. 성능에 큰 차이가없는 경우가 간단하고 이해하기 쉽게, 나는이 사용하는 하위 쿼리를 선호합니다.

  17. ==============================

    17.난 그냥 같은 문제에 대해 생각,하지만 난 부분에서의 하위 쿼리를 사용하고 있습니다. 내가 큰 테이블에서 연결 및 쿼리 필요은 "노예"표는 2800 만 기록을 가지고 있지만 그 결과는 128 너무 작아서 결과 빅 데이터입니다! 나는 그것을 MAX () 함수를 사용하고 있습니다.

    난 그냥 같은 문제에 대해 생각,하지만 난 부분에서의 하위 쿼리를 사용하고 있습니다. 내가 큰 테이블에서 연결 및 쿼리 필요은 "노예"표는 2800 만 기록을 가지고 있지만 그 결과는 128 너무 작아서 결과 빅 데이터입니다! 나는 그것을 MAX () 함수를 사용하고 있습니다.

    우선 등, MySQL의이 optimalize 수 있습니다 내가 그 올바른 방법이라고 생각하기 때문에 LEFT JOIN을 사용하고 있습니다 단지 테스트를위한 두 번째 시간, 나는에 다시 JOIN에 대해 하위 선택합니다.

    LEFT 런타임 가입 : 1.12 초를 런타임 SUB-SELECT : 0.06s를

    18 배 조인을보다 빠르게 부속! 그냥 chokito의 ADV한다. 부속 선택은 끔찍하지만 결과 찾습니다 ...

  18. ==============================

    18.당신이 사용하여 쿼리 속도를하려면 조인

    당신이 사용하여 쿼리 속도를하려면 조인

    은 "내부 조인 / 가입" 조건이 대신 "ON"상태에서 사용할 경우 사용하지 마십시오. 예 :

         select id,name from table1 a  
       join table2 b on a.name=b.name
       where id='123'
    
     Try,
    
        select id,name from table1 a  
       join table2 b on a.name=b.name and a.id='123'
    

    은 "왼쪽 / 오른쪽에 참여" 당신이 왼쪽으로 사용하는 경우 / 바로 어느 한 table.So, "On"으로 그것을 사용 없음 사용하기 위해 모든 행을 얻을 것이다 가입하기 때문에, 조건 "ON"에 사용하지 마십시오. 그래서, "여기서"상태를 사용해보십시오

  19. from https://stackoverflow.com/questions/2577174/join-vs-sub-query by cc-by-sa and MIT license