2012-03-30 2 views
3

SQL 쿼리를 생성하는 PHP 스크립트를 작성 중입니다. 이 스크립트와 데이터베이스는 Joomla CMS 용이며 특히 SOBIPro 구성 요소의 테이블을 쿼리합니다 (이 구성 요소에 입력 된 데이터 사용). 그러나 SOBI Pro 테이블을 처리하는 방식으로 인해 필드의 각 인스턴스가 테이블에서 자체 행으로 처리된다는 것은 다시 가져 오려는 모든 필드에 대해 테이블의 별도 인스턴스를 포함한다는 것을 의미합니다. 이것은 매우 효율적으로 보이지 않으며 사실이 검색에서 시간이 초과됩니다. (이 내 PHP 코드에 의해 후 생성되는)는 다음과 같이MySQL 쿼리 성능 도움말, 동일한 테이블이 여러 개 결합 됨

SQL 쿼리는 다음과 같습니다

SELECT DISTINCT o.id AS entryid, o.parent AS parentID, name.baseData AS title,business.baseData AS business_data, 
    contact_fn.baseData AS contact_fn_data ,contact_ln.baseData AS contact_ln_data ,position.baseData AS position_data, 
    civic1.baseData AS civic1_data ,civic2.baseData AS civic2_data ,mailing.baseData AS mailing_data, 
    community.baseData AS community_data ,municip.baseData AS municip_data ,county.baseData AS county_data, 
    province.baseData AS province_data ,country.baseData AS country_data ,postal.baseData AS descr_data, 
    phone.baseData AS phone_data ,tollfree.baseData AS tollfree_data ,fax.baseData AS fax_data, 
    email.baseData AS email_data ,web.baseData AS web_data ,empTotal.baseData AS empTotal_data 
    FROM jos_sobipro_object AS o 
    INNER JOIN jos_sobipro_field_data AS name ON name.sid = o.id 
    INNER JOIN jos_sobipro_relations AS r ON o.id = r.id 
    LEFT JOIN jos_sobipro_field_data AS business ON business.sid = o.id AND business.fid = 36 
    LEFT JOIN jos_sobipro_field_data AS contact_fn ON contact_fn.sid = o.id AND contact_fn.fid = 74 
    LEFT JOIN jos_sobipro_field_data AS contact_ln ON contact_ln.sid = o.id AND contact_ln.fid = 75 
    LEFT JOIN jos_sobipro_field_data AS position ON position.sid = o.id AND position.fid = 76 
    LEFT JOIN jos_sobipro_field_data AS civic1 ON civic1.sid = o.id AND civic1.fid = 77 
    LEFT JOIN jos_sobipro_field_data AS civic2 ON civic2.sid = o.id AND civic2.fid = 78 
    LEFT JOIN jos_sobipro_field_data AS mailing ON mailing.sid = o.id AND mailing.fid = 79 
    LEFT JOIN jos_sobipro_field_data AS community ON community.sid = o.id AND community.fid = 80 
    LEFT JOIN jos_sobipro_field_data AS municip ON municip.sid = o.id AND municip.fid = 81 
    LEFT JOIN jos_sobipro_field_data AS county ON county.sid = o.id AND county.fid = 82 
    LEFT JOIN jos_sobipro_field_data AS province ON province.sid = o.id AND province.fid = 83 
    LEFT JOIN jos_sobipro_field_data AS country ON country.sid = o.id AND country.fid = 84 
    LEFT JOIN jos_sobipro_field_data AS postal ON postal.sid = o.id AND postal.fid = 85 
    LEFT JOIN jos_sobipro_field_data AS phone ON phone.sid = o.id AND phone.fid = 86 
    LEFT JOIN jos_sobipro_field_data AS tollfree ON tollfree.sid = o.id AND tollfree.fid = 87 
    LEFT JOIN jos_sobipro_field_data AS fax ON fax.sid = o.id AND fax.fid = 88 
    LEFT JOIN jos_sobipro_field_data AS email ON email.sid = o.id AND email.fid = 89 
    LEFT JOIN jos_sobipro_field_data AS web ON web.sid = o.id AND web.fid = 90 
    LEFT JOIN jos_sobipro_field_data AS empTotal ON empTotal.sid = o.id AND empTotal.fid = 106 
    WHERE o.approved = 1 AND o.oType = 'entry' AND name.fid = 36 AND name.baseData <> '' 
    AND name.section = 54 AND r.pid IN (415,418,425,431,458) AND (municip.baseData = "Municipality Name") 
    ORDER BY name.baseData ASC 
상당히 빠른만큼 municip.baseData 검색이 포함되지 않는 작동하는 것 같다

, 어떤에서 이 경우 디렉토리의 15 개 항목에서도 삭제됩니다. 필요한 모든 필드를 다시 가져 오는 동안이 SQL 코드를 설계하는 좋은 방법이 있어야합니다. 이 쿼리는 AJAX를 통해 호출되며 결국 디렉토리에 2000 개 이상의 항목이 생깁니다.

편집 : 당신은 너무 당신이 가지고있는/등/가입 가입/가입 확장 한 경우

id select_type  table type possible_keys key  key_len  ref  rows Extra 
    1 SIMPLE name ref  PRIMARY  PRIMARY  8 const,const  15 Using where; Using temporary; Using filesort 
    1 SIMPLE municip  ref  PRIMARY  PRIMARY  4 const 9 Using where 
    1 SIMPLE o eq_ref PRIMARY,oType PRIMARY  4 [[dbname]].municip.sid 1 Using where 
    1 SIMPLE county ref  PRIMARY  PRIMARY  4 const 10 
    1 SIMPLE province ref  PRIMARY  PRIMARY  4 const 10 
    1 SIMPLE country  ref  PRIMARY  PRIMARY  4 const 8 
    1 SIMPLE postal ref  PRIMARY  PRIMARY  4 const 9 
    1 SIMPLE business ref  PRIMARY  PRIMARY  4 const 15 
    1 SIMPLE contact_fn ref  PRIMARY  PRIMARY  4 const 9 
    1 SIMPLE contact_ln ref  PRIMARY  PRIMARY  4 const 9 
    1 SIMPLE position ref  PRIMARY  PRIMARY  4 const 9 
    1 SIMPLE civic1 ref  PRIMARY  PRIMARY  4 const 10 
    1 SIMPLE civic2 ref  PRIMARY  PRIMARY  4 const 9 
    1 SIMPLE phone ref  PRIMARY  PRIMARY  4 const 10 
    1 SIMPLE tollfree ref  PRIMARY  PRIMARY  4 const 9 
    1 SIMPLE fax  ref  PRIMARY  PRIMARY  4 const 10 
    1 SIMPLE email ref  PRIMARY  PRIMARY  4 const 9 
    1 SIMPLE mailing  ref  PRIMARY  PRIMARY  4 const 11 
    1 SIMPLE community ref  PRIMARY  PRIMARY  4 const 9 
    1 SIMPLE web  ref  PRIMARY  PRIMARY  4 const 10 
    1 SIMPLE empTotal ref  PRIMARY  PRIMARY  4 const 10 
    1 SIMPLE r ref  PRIMARY  PRIMARY  4 [[dbname]].name.sid  3 Using where; Using index; Distinct 
+0

이 쿼리에서 SQL EXPLAIN을 실행하고 출력을 게시하십시오. –

+0

http://dev.mysql.com/doc/refman/5.1/en/using-explain.html –

+0

EXPLAIN 출력이 본문에 추가되었습니다. – wolfergiga

답변

1

많은 시간이의 SQL 엔진 자체에 걸려 얻을 것이다 다음은 EXPLAIN 출력, 요청에 따라입니다 작은 결과 세트를 찾고 덜 효율적인 방식으로 링크를 백필하려고 시도합니다. 귀하의 질의가 잘 보입니다.

PRIMARY 테이블 (FROM jos_sobipro_object AS o)은 실제로 쿼리의 KEY 구동 요소입니다. MySQL을 사용하여 "STRAIGHT_JOIN"특별한 키워드 .. 쿼리의

SELECT STRAIGHT_JOIN DISTINCT ... 나머지 ...

STRAIGHT_JOIN 내가 여기에 열거 한 순서대로 쿼리를 다만 할 수있는 최적화 지시를 추가하십시오. 그런 다음 데이터를 쿼리하는 첫 번째 테이블을 아는 것이 더 빠를 것입니다.

인덱스 정보를 정확하게 보지 못했다고 말하면 jos_sobipro_field_data에 대한 색인을 지정하여 (SID, FID)의 "조회"데이터를 얻습니다.

나는 14+ 만 기록의 정부 데이터 기본 테이블 및 룩업 테이블을 22 +에 가입 유사한 접근 방식을 했어. MySQL은 30 시간 이상 걸릴 것입니다. STRAIGHT_JOIN을 추가하면 약 3 시간 후에 쿼리가 완료됩니다 (예상했던대로).