2012-03-30 30 views
3

我正在編寫一個PHP腳本來創建一個SQL查詢。這個腳本和數據庫用於Joomla CMS,特別是查詢SOBIPro組件的表格(使用在這個組件中輸入的數據)。但是,由於處理SOBI Pro表的方式,在表中每個字段的實例都是它自己的行,這意味着包含我想要撤回的每個字段的表的單獨實例。這看起來效率不高,實際上在這一次搜索中超時。MySQL查詢性能幫助,許多同一表正在加入

SQL查詢如下(這是由我的PHP代碼生成後):

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多個條目。

編輯:這裏是EXPLAIN輸出的要求:

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,發佈輸出。 – 2012-03-30 03:25:46

+0

http://dev.mysql.com/doc/refman/5.1/en/using-explain.html – 2012-03-30 03:26:11

+0

EXPLAIN輸出添加到主文本中。 – wolfergiga 2012-03-30 03:37:26

回答

1

很多時候,當你有一個過度擴展JOIN /加盟/加盟/等你有,SQL引擎將得到掛在自身試圖找到小的結果集並以較低效率的方式回填鏈接。你的查詢看起來不錯。

您的PRIMARY表(來自jos_sobipro_object AS o)確實是查詢的關鍵驅動元素。試着增加與MySQL的「STRAIGHT_JOIN」特殊的關鍵字..

SELECT DISTINCT STRAIGHT_JOIN ...查詢休息...

STRAIGHT_JOIN告訴只是做我在這裏列出的順序查詢優化器。然後它會更快地工作知道第一個表是查詢數據的主要表。

這就是說,並沒有完全看到索引信息,我會明確地有一個索引jos_sobipro_field_data獲取(查找)數據(SID,FID)。

我不得不採取類似的方法,使用主表中的1400萬條記錄的政府數據並加入22個查找表。 MySQL會在30個小時後掛起。通過添加STRAIGHT_JOIN,查詢在大約3小時內完成(正如它所做的那樣)。