문제

이 쿼리를 최적화하려면 어떻게 해야 합니까?

SELECT * FROM
    (SELECT `item`.itemID, COUNT(`votes`.itemID)  AS `votes`,
           `item`.title, `item`.itemTypeID, `item`.
           submitDate, `item`.deleted, `item`.ItemCat,
           `item`.counter, `item`.userID, `users`.name,
           TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' ,
           `myItems`.userID as userIDFav, `myItems`.deleted as myDeleted
      FROM    (votes `votes` RIGHT OUTER JOIN item `item`
                  ON (`votes`.itemID = `item`.itemID))
           INNER JOIN
              users `users`
           ON (`users`.userID = `item`.userID)
    LEFT OUTER JOIN
              myItems `myItems`
           ON (`myItems`.itemID = `item`.itemID)
     WHERE (`item`.deleted = 0)
     GROUP BY `item`.itemID,
              `votes`.itemID,
              `item`.title,
              `item`.itemTypeID,
              `item`.submitDate,
              `item`.deleted,
              `item`.ItemCat,
              `item`.counter,
              `item`.userID,
              `users`.name,
              `myItems`.deleted,
              `myItems`.userID
    ORDER BY `item`.itemID DESC) as myTable
where myTable.userIDFav = 3 or myTable.userIDFav is null
            limit 0, 20 

나는 MySQL을 사용하고 있습니다

감사해요

도움이 되었습니까?

해결책

물론 @theomega가 말했듯이 실행 계획을 살펴보십시오.

그러나 나는 또한 당신의 진술을 "정리"하는 것을 제안하고 싶습니다.(어느 것이 더 빠른지는 모르겠습니다. 이는 테이블 크기에 따라 다릅니다.) 일반적으로 저는 깔끔한 문장으로 시작하여 거기서부터 최적화를 시작하려고 합니다.그러나 일반적으로 깔끔한 문은 최적화 프로그램이 좋은 실행 계획을 세우는 것을 더 쉽게 만듭니다.

따라서 상황을 느리게 만들 수 있는 귀하의 진술에 대한 몇 가지 관찰 사항은 다음과 같습니다.

  • 두 개의 외부 조인(최적자가 사용할 인덱스를 파악하기 어렵게 만듭니다)
  • 그룹화
  • 그룹화할 열이 많음

내가 이해하는 한 귀하의 SQL은 다음 명령문이 귀하가 수행하는 작업의 대부분을 수행해야 합니다.

SELECT `item`.itemID, `item`.title, `item`.itemTypeID, `item`.
       submitDate, `item`.deleted, `item`.ItemCat,
       `item`.counter, `item`.userID, `users`.name,
       TIMESTAMPDIFF(minute,`submitDate`,NOW()) AS 'timeMin' 
  FROM    (item `item` INNER JOIN users `users`
       ON (`users`.userID = `item`.userID)

어디

물론 외부 조인 테이블의 정보가 누락되므로 하위 선택을 통해 필요한 열을 추가하는 것이 좋습니다.

SELECT `item`.itemID, 
       (SELECT count (itemID)
        FROM votes v
       WHERE v.itemID = 'item'.itemID) as 'votes', <etc.>

이렇게 하면 하나의 외부 조인과 그룹 기준을 제거할 수 있습니다.외부 조인은 하위 선택으로 대체되므로 "깔끔한" 문에는 좋지 않을 수 있는 절충안이 있습니다.

item과 myItems 사이의 카디널리티에 따라 동일한 작업을 수행하거나 외부 조인을 사용해야 합니다(그러나 그룹 기준을 다시 도입할 필요는 없음).

도움이 되었기를 바랍니다.

다른 팁

분석기는이 쿼리에 대해 무엇을 말합니까? 테이블에 얼마나 많은 행이 있는지에 대한 지식이 없으면 최적화를 말할 수 없습니다. 따라서 분석기를 실행하면 어떤 부품 비용이 드는지 볼 수 있습니다.

몇 가지 빠른 반 랜덤 생각 :

ItemID 및 UserID 열이 색인되어 있습니까?

쿼리 시작에 "설명"을 추가하고 실행하면 어떻게됩니까? 인덱스를 사용합니까? 그들은 합리적입니까?

전체 내부 쿼리를 실행하고 필터를 필터링해야합니까, 아니면 이동할 수 있습니까? where myTable.userIDFav = 3 or myTable.userIDFav is null 내부 쿼리에 참여 하시겠습니까?

그룹에 너무 많은 필드가있는 것 같습니다. 그중 하나는 ItemId이기 때문에 내부 선택을 사용하여 그룹화를 미리 형성하고 원하는 필드 세트를 반환하기 위해 외부 선택을 사용할 수 있다고 생각합니다.

WHERE 절을 추가 할 수 없습니다 mytable.useridfav = 3 또는 mytable.useridfav는 null입니다 에게 어디 (item.deleted = 0)?

문안 인사
Lieven

쿼리가 구축되는 방식을 살펴보십시오. 많은 물건을 결합한 다음 출력을 20 행으로 제한합니다. 항목과 신분에 대한 외부 조인이 있어야합니다. 조건은이 두 테이블에만 적용되므로 출력을 처음 20 행으로 제한 한 다음 결합 및 집계를 제한합니다. 여기서 당신은 폐기 될 많은 작업을 수행하고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top