2014-02-17 2 views
1

여기에 최신 SQL 게시물 5 개를 가져 오는 SQL 쿼리가 있습니다. 나는 그것을 만들기를 원한다 그래서 그것은 또한 총 조회수와 전체 뉴스 덧글을 동일한 쿼리에서 가져온다. 그러나 많은 양의 데이터로 작업 할 때 내가 만든 쿼리가 약간 느려서 더 나은 솔루션을 찾을 수 있는지 알아보기 위해 노력하고 있습니다. 여기에는 다음과 같습니다 : 열을 유형, 코드를 POST_ID ID을, 인덱스를 돕는 http://sqlfiddle.com/#!2/d3ecbf/1여러 테이블을 사용하여 SQL 쿼리를 최적화하는 방법

답변

0

은 MySQL이 특히 큰 데이터 세트를 처리 할 때, 하위 쿼리 문제를 알고 있으며, 조인

SELECT n.*, 
     `id` as `newscode`, 
     COALESCE(l.TotalLikes, 0) AS `total_likes`, 
     COALESCE(c.TotalComments, 0) AS `total_comments` 
FROM `news` n 
     LEFT JOIN 
     ( SELECT Code, COUNT(*) AS TotalLikes 
      FROM `likes` 
      WHERE `type` = "newspost" 
      GROUP BY Code 
     ) AS l 
      ON l.`code` = n.`id` 
     LEFT JOIN 
     ( SELECT post_id, COUNT(*) AS TotalComments 
      FROM `news_comments` 
      GROUP BY post_id 
     ) AS c 
      ON c.`post_id` = n.`id` 
ORDER BY n.`id` DESC LIMIT 5; 

이유는 당신이 위와 같이 조인을 사용하면, MySQL은 결과를 실현하는 것입니다 빠른 조회를 위해 메모리 테이블과 해시 post_id를에서로

SELECT post_id, COUNT(*) AS TotalComments 
FROM `news_comments` 
GROUP BY post_id 

:이 쿼리의 시작시가 처음 필요한 하위 쿼리, 예를 들어,의, MySQL은 결과를 넣어 것입니다. 그런 다음 news의 각 행에 대해이 해시 테이블에서 TotalComments 만 조회해야합니다. 상관 하위 쿼리를 사용하면 news의 각 행에 대해 한 번 쿼리가 실행됩니다. news이 큰 경우 실행 횟수가 많습니다. 초기 결과 집합이 작 으면 성능상의 이점을 볼 수 없으며 더 나쁠 수도 있습니다.

마지막으로 SQL 바이올린에

예를 들면, 당신은 인덱스에 news_commentslikes에서 관련 필드를 할 수 있습니다.이 특정 쿼리에 대해 나는 다음 인덱스가 도움이 될 것입니다 생각 :

CREATE INDEX IX_Likes_Code_Type ON Likes (Code, Type); 
CREATE INDEX IX_newcomments_post_id ON news_comments (post_id); 

것은 두에 최초의 인덱스를 분할해야 할 수도 있지만 :

CREATE INDEX IX_Likes_Code ON Likes (Code); 
CREATE INDEX IX_Likes_Type ON Likes (Type); 
+0

Im 실행시 'on clause'에 'Unknown column'n.newscode '오류가 발생합니다. – user3205106

+0

정확히 무엇을 의미합니까? 별도의 표가 있습니다. – user3205106

+0

'total_likes'를 얻는 하위 쿼리에서 WHERE 절에 다음을 포함합니다 :'\'code \'= \'newscode \''. 'newscode'가 여기서 말하는 것은 무엇입니까? 나는 그것들이 별개의 테이블이라는 것을 알고 있지만 아마도 그들은 연결되어있을 것입니다. 그렇지 않으면 당신은 좋아하는 총 수를 얻고 있습니다. 관계가없는 한 모든 행에 대해 동일한 수입니다. – GarethD

0

먼저 체크 : 여기

SELECT *, 
`id` as `newscode`, 
(SELECT COUNT(*) FROM `likes` WHERE `type`="newspost" AND `code`=`newscode`) as `total_likes`, 
(SELECT COUNT(*) FROM `news_comments` WHERE `post_id`=`newscode`) as `total_comments` 
FROM `news` ORDER BY `id` DESC LIMIT 5 

뿐만 아니라 SQLFiddle이다.

0

내가 가장 익숙한 T-SQL이라고 가정합니다.

먼저 색인을 확인합니다. 그게 좋아 보인다면, 진술서를 확인해 봐. 쿼리 맵에서 결과를 채우는 방법을 확인하십시오.

SQL은 뒤로 작동하므로 마지막 AND 문으로 시작하고 거기에서 시작됩니다. 코드별로 모두 그룹화 한 다음 입력하고 마침내 계산합니다.

지금은 날짜에 관계없이 특정 코드로 모든 것을 포착하고 있습니다. 최신 정보를 원한다고 말하면 어딘가에 날짜 열이 있다고 가정합니다.

속도를 높이려면 WHEREAND을 추가하고 날짜를 기록하십시오. 지난 24 시간, 지난 주, 뭐든간에. 당신이 사용을 다시 작성할 수

+1

질문이 T-SQL과 관련된다고 가정 할 때 질문에 'MySQL'태그가 붙었습니다. SQL이 거꾸로 돌아가는 문장은 마지막 AND 문으로 시작합니다.이 문장은 선택하지 않은 테이블로 시작하고, 조인을 처리합니다 (다른 말을하지 않는 한 어떤 순서로든). 그런 다음 거래합니다. where 절로, 옵티마이 저가 가장 빠른 것으로 간주하는 순서로 다시. – GarethD

+0

네가 맞다. 나는 태그를 확인하지 않았다. 분명히, SQL은 테이블 집계'FROM'으로 시작하지만, 그 후에 데이터는 절대적으로 '역순', 즉'WHERE','GROUP','HAVING','SELECT','ORDER BY' 구문 분석됩니다. 내 제안은 테이블과 조인이 처리 된 후 다음 단계 인 'WHERE' 절을 구체화하는 것이 었습니다. – Phoenix

1
나는 newstotal_likestotal_comments 필드를 추가하는 것이 좋습니다 것입니다

like 및/또는 comment가 추가되거나 제거 될 때마다 증가/감소되는 테이블.

likesnews_comments 테이블은 역사적인 목적으로 만 사용해야합니다.

이 심한 계산은 페이지가로드 될 때마다 수행되어서는 안됩니다. 이는 리소스가 완전히 낭비되기 때문입니다.

+0

@ user3205106, 어디로 가고 있었는지, 좋아요/주석 표의 INSERT 트리거에 있어야합니다. 이것은 일반적인 문제입니다. 특히 웹에서 DENORMALIZE를 사용하면 쿼리가 크롤링에 영향을 미칠 수 있습니다. – DRapp

+0

감사합니다 @DRapp 일반적으로 말하기 사용자는 OP가 무언가를 좋아할 때 결정을 내리지 않는 한 일반적으로 Like 및 Un-Like 작업을 모두 수행 할 수 있기 때문에 INSERT뿐 아니라 DELETE 일 것임을 언급하는 것을 잊어 버렸다고 가정합니다. 주석이 검토 될 가능성이 높다는 점을 고려하여 주석에도 동일한 규칙을 적용 할 수 있습니다. 따라서 내 대답의 증가/감소 부분. – MonkeyZeus

+0

이 맞으면 삽입, 업데이트 및 삭제가 있어야하지만 총계의 비정규 화에 대해서는 더 나은 고려 사항이됩니다. – DRapp

관련 문제