2017-01-29 1 views
1

그래서 나는이 같은 쿼리가 :여러 테이블을 조인하는 쿼리에서 MySQL "주문 제한 한도"를 최적화하는 방법은 무엇입니까?

SELECT tablea.name, tablea.views from tablea inner 
join tableb on (tablea.id = tableb.id and tablea.balance > 0) 
order by tablea.views asc limit 1 

그러나, 문제는 내가 그것을 실행하면, 그것은 아주 느린 (4+ 초)를 실행한다는 것입니다. 흥미롭게도 'order by'절을 제거하면 한계 1을 유지하면서 0.005 초 (약)로 실행됩니다. 더욱 흥미로운

: 나는, 즉 :

SELECT tablea.name, tablea.views from tablea 
where tablea.balance > 0 
order by tablea.views asc limit 1 

쿼리는 일반적으로 0.005 초에서 실행을 TableB의 할에 가입하지 않는 경우.

주 : TABLEA에

  • 열 뷰
  • TABLEA 및 TableB의 인덱싱되는 ID의 관점에서 1~1의 관계를 가지며, 대략 동일한 행 양을 갖는다.

왜 첫 번째 쿼리, 'order by'가 제거 될 때 첫 번째 쿼리와 두 번째 쿼리 사이에 성능에 큰 차이가 있습니까?

어쨌든 두 테이블을 결합 할 때 정렬이 훨씬 빨라지겠습니까?

+1

원본 결합 쿼리에서'EXPLAIN'을 (를) 실행할 수 있습니까? 실제로 거기에서 무슨 일이 일어나는지 봅시다. –

+0

성능에 대한 질문은 모든 관련 테이블에 대한 CREATE TABLE 문과 EXPLAIN의 결과를 항상 요구합니다 – Strawberry

답변

1

여기서 무슨 일이 벌어지고 있는지에 대한 하나의 가능한 설명은 MySQL이 의 순서대로 선택하기 전에보다 실제 결합을한다는 것입니다. ORDER BY 절을 제거 할 때 원래 쿼리에서 보았 듯이 자체적으로 조인하는 것은 성능상의 문제가 아닙니다. 그때는 아마 내가 추측 것을 확인,

SELECT * 
FROM 
(
    SELECT tablea.name, 
      tablea.views 
    FROM tablea 
    INNER JOIN tableb 
     ON tablea.id = tableb.id AND 
      tablea.balance > 0 
) t 
ORDER BY t.views ASC 
LIMIT 1 

을이 작동하는 경우이 극복하는 한 가지 방법은 주문 후 하위 쿼리에 원래 쿼리를 래핑, 그리고 것입니다. 이 경우 하위 쿼리는 MySQL이 실제 하위 쿼리 결과 인 레코드 만 정렬하도록합니다. 어쨌든 이러한 쿼리에 EXPLAIN을 실행하는 습관을 들여야합니다. 내 생각 엔 원래의 쿼리에 합류 할 때 인덱스가 사용되지 않고 효과적이지 않다는 것입니다.

참조 :Slow query when using ORDER BY

0
Given INDEX(x) 
ORDER BY x LIMIT 1 

편리 인덱스를 사용하여 첫 번째 항목을 선택할 것인가

Given INDEX(x) 
WHERE ... 
ORDER BY x LIMIT 1 

또한 일부 초기 행이 만족 인덱스 및 희망을 사용할 수 있습니다 WHERE. 그렇지 않다면, 전체 테이블을 스캔하여 한 행을 찾아야 할 수도 있습니다!

Given INDEX(a, x) 
WHERE a = 12 
ORDER BY x LIMIT 1 

문제 없음 - 색인에서 a = 12를 찾습니다. 첫 번째 항목을 선택하십시오.

Given INDEX(a, x) 
WHERE a > 12 
ORDER BY x LIMIT 1 

이제 색인이 좋지 않습니다. 모든 행을> 12로 정렬하고 x로 정렬 한 다음 한 행을 전달해야합니다.완전히 만족시킬 수 WHEREORDER BY 경우 일반적

은 다음 LIMIT n이 최적화 될 수있다. (이것은 더 GROUP BY을지지 않습니다, 또는 GROUP BYORDER BY동일이다.) 하나 개의 테이블로의

. JOIN 두 개 (또는 그 이상)의 테이블은 더 복잡해집니다. 두 테이블을 사용하면 Optimizer가 하나의 테이블을 선택하고 그 테이블에서 가능한 것을 찾은 다음 다른 테이블에 중첩 루프 조인을 수행합니다.

항상 (항상은 아님) WHERE 절 (한 테이블에서)은 Optimizer에게 "pick me"를 알려줍니다. 해당 테이블이 ORDER BY 인 경우 위의 토론이 시작될 수 있습니다.

WHERE 절이 없으면 최적화 프로그램은 일반적으로 작은 테이블로 시작됩니다. (참고 : 테이블 크기는 행 을 기반으로이을 추정하고 때마다 정확하지 않을 수 있습니다.)

첫 번째 쿼리는 JOIN tableb... 대신 WHERE EXISTS (... tableb ...)를 사용하여 가속화 될 수 있습니다. Optimizer는이를 최적화 할 가치가있는 것으로 봅니다. 당신의 "0.005 초" "운"이라고

기타 등 등

참고. 당신이 깊이 파고하려면

제공 SHOW CREATE TABLE 자세한 내용은 가능한 EXPLAIN FORMAT=JSON SELECT ... 경우, EXPLAIN SELECT (그래서 우리는 무엇을 최적화 결정 논의 할 수)와, (그래서 우리는 인덱스 (들) 등을 볼 수 있습니다). 또한 my indexing cookbook을 참조하십시오.

관련 문제