2013-01-22 3 views
1

저는 다양한 솔루션 내에서 항상 데이터베이스를 사용하지만 실제로는 설계하지 않았습니다. 따라서, 나는 SQL의보다 미세한 부분에 익숙하다. 나는 많은 테이블을 가진 데이터베이스를 가지고 있지만, 2 가지 주요한 것들을 가지고있다 : 아이템 - 리비전과 함께 변경되지 않는 데이터를위한 다른 많은 테이블을 참조한다. 엔트리 - 리비젼으로 바뀌는 데이터를위한 다른 많은 테이블을 참조한다. 각 아이템 따라서 하나 이상의 수정본 (모든 관련 데이터 포함)을 갖게됩니다.MySQL 쿼리의 속도 문제보기

모든 수정본 (결과적으로 항목)에 대한 모든 데이터를보기로 선택하고 싶습니다. 다음과 같이 단일 쿼리를 구성했습니다.

CREATE VIEW Single_Query 
AS 
SELECT i.REF_CODE AS REF 
gp.GROUP_NAME AS Group 
v.VERSION_NUMBER AS Version 
GROUP_CONCAT(DISTINCT(cy.COUNTRY_DESCRIPTION) SEPARATOR ', ') AS Country 
ey.PUB_DATE AS Published 
GROUP_CONCAT(DISTINCT(ct.CONTRIBUTOR_NAME) SEPARATOR ', ') AS Author 
i.ISBN_CODE AS ISBN 
GROUP_CONCAT(DISTINCT CONCAT(cn.COMPONENT_NUMBER, _utf8', ',cn.COMPONENT_DESCRIPTION) SEPARATOR '; ') AS Contents 
ey.NOTES AS Notes 
i.PRICE AS Price 
cl.COLOUR_DESCRIPTION AS Colour 
FROM entry AS ey 
JOIN item AS i ON ey.ITEM_ID = i.ITEM_ID 
JOIN group AS gp ON i.GROUP_ID = gp.GROUP_ID 
JOIN version AS v ON ey.VERSION_ID = v.VERSION_ID 
JOIN link_country_item AS lci ON i.ITEM_ID = lci.ITEM_ID 
JOIN country AS cy ON lci.COUNTRY_ID = cy.COUNTRY_ID 
LEFT JOIN link_entry_contributor AS lec ON ey.ENTRY_ID = lec.ENTRY_ID 
LEFT JOIN contributor AS ct ON lec.CONTRIBUTOR_ID = ct.CONTRIBUTOR_ID 
JOIN contents AS cn ON i.ITEM_ID = cn.ITEM_ID 
JOIN colour AS cl ON ey.COLOUR_ID = cl.COLOUR_ID 
GROUP BY REF_CODE, VERSION_NUMBER 

이 작업을 완료하는 데는 몇 초 밖에 걸리지 않습니다. 그러나 항목 데이터 (및 모든 참조 된 데이터) 및 항목 데이터 (및 모든 참조 된 데이터)에 대한 임시 테이블을 만들 스크립트를 실행하면 ITEM_ID에 단일 JOIN이있는 2 개의 임시 테이블에서 전체 로트를 선택한 다음 완료하는 데는 0.5 초도 채 걸리지 않습니다.

많은 다른 참조 테이블이 있음을 유의하십시오 (명확하게하기 위해 생략했습니다).

도움이된다면 항목 테이블은 그룹을 설정하고 (많은 many_link_country_item 테이블을 통해) 내용 테이블을 참조합니다.

엔트리 테이블은 버전, 기여자 (많은 수의 link_entry_contributor 테이블을 통해) 및 색상 표를 참조합니다.

문제는 뷰에서 사용할 수 없거나 (적어도 내가 어떻게 발견하지 못했는지) 항상 임시 테이블을 사용하고 싶지 않다는 것입니다. 이 시나리오에서 더 빠르게 실행되도록보기에서 SQL을 분할하는 좀 더 우아한 방법이 있습니까? 사전

이안

답변

0

에서

많은 덕분에 나는 약간 질의 순서를 재구성하고, REF_CODE에 대한 의견을 참조했습니다. 당신이 맞다면, 원래의 색인 대답은 당신에게 적용되지 않을 것입니다. 그러나 항목 테이블이 기본 위치에있는 경우 인덱스가 (REF_CODE, ITEM_ID) 인 경우 성능에 도움이됩니다 (테이블로 시작하는 경우). GROUP BY 절에 해당하는 인덱스입니다.

CREATE VIEW Single_Query 
AS 
SELECT STRAIGHT_JOIN 
     i.REF_CODE AS REF 
     gp.GROUP_NAME AS Group 
     v.VERSION_NUMBER AS Version 
     GROUP_CONCAT(DISTINCT(cy.COUNTRY_DESCRIPTION) SEPARATOR ', ') AS Country 
     ey.PUB_DATE AS Published 
     GROUP_CONCAT(DISTINCT(ct.CONTRIBUTOR_NAME) SEPARATOR ', ') AS Author 
     i.ISBN_CODE AS ISBN 
     GROUP_CONCAT(DISTINCT CONCAT(cn.COMPONENT_NUMBER, _utf8', ',cn.COMPONENT_DESCRIPTION) SEPARATOR '; ') AS Contents 
     ey.NOTES AS Notes 
     i.PRICE AS Price 
     cl.COLOUR_DESCRIPTION AS Colour 
    FROM 
     item AS i 
     JOIN entry ey 
      ON i.ITEM_ID = ey.ITEM_ID 
      JOIN version AS v 
       ON ey.VERSION_ID = v.VERSION_ID 
      JOIN colour AS cl 
       ON ey.COLOUR_ID = cl.COLOUR_ID 
      LEFT JOIN link_entry_contributor AS lec 
       ON ey.ENTRY_ID = lec.ENTRY_ID 
       LEFT JOIN contributor AS ct 
        ON lec.CONTRIBUTOR_ID = ct.CONTRIBUTOR_ID 
     JOIN group AS gp 
      ON i.GROUP_ID = gp.GROUP_ID 
     JOIN link_country_item AS lci 
      ON i.ITEM_ID = lci.ITEM_ID 
      JOIN country AS cy 
       ON lci.COUNTRY_ID = cy.COUNTRY_ID 
     JOIN contents AS cn 
      ON i.ITEM_ID = cn.ITEM_ID 
    GROUP BY 
     REF_CODE, 
     VERSION_NUMBER 
+0

답장을 보내 주셔서 감사합니다. DRapp. 시간을내어 주셔서 감사합니다. REF_CODE 및 VERSION_ID에 대한 'Entry'테이블의 인덱스를 만들 수 있는지 확신 할 수 없습니다. REF_CODE가 'Entry'테이블에 직접 연결되어 있지 않아서 - 'Item'테이블에 연결되고 ' Entry/Item '링크를 클릭합니다. 내가 대답을 오해하지 않았다면 ... – user2001184

+0

@ user2001184, 수정 된 대답. – DRapp

+0

멋진 소식입니다! 수정안을 적용하고 쿼리 시간이 29 초에서 거의 순간적으로 줄어 들었습니다. 이 모든 도움에 많은 감사드립니다. 나는 미래에 이런 종류의 구조를 적용하는 것을 확실히 기억할 것입니다. :-) – user2001184