2016-09-20 2 views
2

현재 내 웹 사이트에서 기사에 태그가 있습니다.mysql 무엇이 더 빠를 것입니까?

내가 지금처럼 그들을 위해 카테고리 태그 목록을 수집하기 위해 MySQL의 쿼리를 수행 각각에 대한 기사 목록을 통해 내가 루프 : 이제

SELECT c.`category_name`, c.`category_id` 
FROM `articles_categorys` c 
    INNER JOIN `article_category_reference` r ON c.category_id = r.category_id 
WHERE r.article_id = 8136 
ORDER BY r.`category_id` = *IDHERE* DESC, r.`category_id` ASC 
LIMIT 4 

, 내가 가진 페이지를 상상 30 말 기사가 한 번에 표시되면 위 쿼리가 30 번 수행됩니다. 나는 그것이 끔찍하다고 상상한다. 내가하기로 결정 무엇

이 페이지의 모든 article_ids의 배열을이었고, 다음이 대신 수행

SELECT c.`category_name`, c.`category_id`, r.article_id 
FROM `articles_categorys` c 
INNER JOIN `article_category_reference` r ON c.category_id = r.category_id 
WHERE r.article_id = 8136 OR r.article_id = 8130 OR r.article_id = 8127 
    OR r.article_id = 8125 OR r.article_id = 8123 OR r.article_id = 8120 
    OR r.article_id = 8119 OR r.article_id = 8117 OR r.article_id = 8116 
    OR r.article_id = 8112 OR r.article_id = 8107 OR r.article_id = 8106 
    OR r.article_id = 8037 OR r.article_id = 8104 OR r.article_id = 8103 

내가 그 위에서 발견 된 배열을 통해 단지 루프에 PHP를 사용하여 일치 article_id를 현재 기사로 보내고 일치하면 category_name을 echo합니다. 유일한 문제는 article_id 당 4 개로 제한 할 수 없다는 것입니다.

새로운 접근 방식이 더 좋든 나쁘거나 두 가지 모두가 끔찍한가요?

예 데이터 사용하기 :

단지 좋은 질의를 할 때로 충분하지
CREATE TABLE `articles_categorys` (
    `category_id` int(11) NOT NULL, 
    `category_name` varchar(32) COLLATE utf8_bin NOT NULL 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin; 

CREATE TABLE `article_category_reference` (
    `ref_id` int(11) NOT NULL, 
    `article_id` int(11) NOT NULL, 
    `category_id` int(11) NOT NULL 
) ENGINE=MyISAM DEFAULT CHARSET=latin1; 

INSERT INTO `articles_categorys` (`category_id`, `category_name`) VALUES 
(22, 'Site Info'), 
(1, 'Editorial'), 
(2, 'Review'), 
(3, 'Interview'), 
(4, 'Game Sale'), 
(5, 'Steam'), 
(6, 'Indie Game'), 
(7, 'Crowdfunding'), 
(8, 'Game Bundle'), 
(9, 'Free Game'), 
(10, 'MMO'); 

INSERT INTO `article_category_reference` (`ref_id`, `article_id`, `category_id`) VALUES 
(15, 6231, 22), 
(14, 6231, 1), 
(16, 6231, 2), 
(17, 6231, 3), 
(18, 6231, 4), 
(19, 6231, 9), 
(20, 6231, 10); 
+0

시도해보세요. IN (8136, 8130, 8127, .......)' – RiggsFolly

+0

IN()에 대해 마음을 먹었습니까? –

+0

일반적으로 SQL 쿼리는 모든 웹 페이지의 병목 지점이므로 대개는 똑똑한 쿼리를 사용하는 것이 가장 좋은 솔루션입니다. 결과에 태그를 그룹화하려면'ORDER BY r.article_id'를 잊지 마세요. 그러면 코드가 저장됩니다. –

답변

1

SQL을 사용하면 벤치 마크를 수행하고 쿼리에서 EXPLAIN을 수행하여 어느 것이 더 빠를 지 항상 확인하는 것이 좋습니다. 하지만 엄지 손가락의 규칙에 따라 IN은 아마 여러 개의 OR을 능가 할 것입니다. 그래도 결과를 네 개로 제한하는 문제가 남아 있습니다. 의견에서 말한 것과는 달리 모든 데이터를 가져온 다음 PHP를 사용하여 4 개의 항목 만 선택하는 것은 좋지 않습니다. 잠재적으로 수천 개의 행을 검색하여 백을 표시 할 수 있습니다.

SET @rank=null, @val=null; 
SELECT * FROM (

    SELECT c.`category_name`, c.`category_id`, r.article_id, 
    @rank := IF(@val = r.article_id, @rank+1,1) as rank, 
    @val := r.article_id 
    FROM `articles_categorys` c 
    INNER JOIN `article_category_reference` r ON c.category_id = r.category_id 
    WHERE r.article_id IN (8136, /* fill this up accordingly */) 

    ORDER BY r.`category_id` ASC 
) AS a WHERE rank < 5; 

자세한 내용은이 우수한 Q & A 참조 : 한마디로 Using LIMIT within GROUP BY to get N results per group?

을, 어떤이 쿼리가하는 각 레코드에 순위를 asign하는 것입니다. 처음에는 순위가 null이고, 첫 번째 행은 null로 설정됩니다. r.category_id는 동일하게 유지되지만 category_id가 변경되면 계속 증가합니다.

+0

정말 흥미 롭습니다. 이전에는 그런 것을 본 적이 없습니다! 당신은 내게 새로운 것을 볼 수있게 해주었습니다. 그리고 그것은 제가 원하는 방식으로 정확히 작동하는 것 같습니다. 덕분에 이것을 올바른 해결책으로 생각할 것입니다. – NaughtySquid

+0

실제로 라이브 데이터에 대한 실제 테스트를하고 있으며 4로 제한하지 않는 것 같습니다. "ORDER BY r.'category_id' = * IDHERE * DESC"을 꺼 냈습니다. 당신이 의미하는 바를 알고 있다면, 우리는 카테고리 ID를 가지고 있지 않습니다. 우리는 쿼리 자체에서 그것을 잡아냅니다. 그들 모두에게 1 등급을주는 것 같습니다. – NaughtySquid

+0

표 형식의 데이터를 최상의 형식으로 제 질문으로 가져 오는 좋은 방법은 무엇입니까? – NaughtySquid

관련 문제