2012-03-01 170 views
0

我想運行一個查詢,需要5秒鐘執行100000行。查詢如下。我試過所有可能的索引。請告訴我我錯過了什麼。mysql查詢運行速度很慢。請幫我索引

select distinct db_books.bookid as id 
, request_type.name as book_type 
, request_type.id as book_type_id 
, db_books.subject as subject 
, sender_user.uid as sender_user_id 
, sender_user.username as sender_user 
, sender_company.companyid as sender_company_id 
, sender_company.companyname as sender_company 
, sender_team_id.teamid as sender_team_id 
, sender_team_id.name as sender_team 
, GROUP_CONCAT(distinct receiver_user_details.uid separator '|') as receiver_user_id 
, GROUP_CONCAT(distinct receiver_user_details.username separator '|') as receiver_user 
, GROUP_CONCAT(distinct receiver_company.companyid separator '|') as receiver_company_id 
, GROUP_CONCAT(distinct receiver_company.companyname separator '|') as receiver_company 
, GROUP_CONCAT(distinct receiver_team_details.teamid separator '|') as receiver_team_id 
, GROUP_CONCAT(distinct receiver_team_details.name separator '|') as receiver_team 
, status.id as statusid 
, status.name as status 
, db_books.modifydate as modified_date 
, db_books.createddate as creation_date 
, state.id as stateid 
, state.name as state 
, assignee.uid as assignee_user_id 
, assignee.username as assignee_user 
, purpose.name as purpose 
, purpose.id as purposeid 
, g.name as entityname 
, g.entityid as entityid 
from db_books db_books 
inner join db_users sender_user on (sender_user.deleted=0 and sender_user.uid=db_books.sndrUserid) 
inner join db_companies sender_company on (sender_company.deleted=0 and sender_company.companyid=db_books.sndrCompanyid) 
inner join db_companies receiver_company on (receiver_company.deleted=0 and receiver_company.companyid=db_books.target_company_id) 
inner join db_request_types request_type on (request_type.id=db_books.book_type_id) 
left outer join db_teams sender_team_id on (sender_team_id.deleted=0 and sender_team_id.teamid=db_books.sender_team_id) 
left outer join db_books_to_users receiver_user on (receiver_user.bookid=db_books.bookid) 
left outer join db_users receiver_user_details on (receiver_user_details.uid=receiver_user.userid) 
left outer join db_books_to_teams receiver_teams on (receiver_teams.bookid=db_books.bookid) 
left outer join db_teams receiver_team_details on (receiver_team_details.teamid=receiver_teams.teamid) 
left outer join db_request_status status on (status.id=db_books.statusid) 
left outer join db_request_state_types state on (state.id=db_books.request_state_id) 
left outer join db_request_purpose purpose on (purpose.id=db_books.request_purpose_id) 
left outer join db_users assignee on (assignee.uid=db_books.assignee) 
left outer join db_books_details mdtl on (mdtl.deleted=0 and mdtl.bookid=db_books.bookid) 
left outer join db_entities g on (g.deleted=0 and g.entityid=mdtl.entityid) 
where 1=1 
and 
(db_books.sndrUserid=25000000003265 
or db_books.sender_team_id in (
      select a.teamid from db_team_users a 
      inner join db_teams b on (b.teamid=a.teamid and b.deleted=0) 
      where a.userid=25000000003265 
     ) 
or db_books.bookid in (
    select distinct bookid from db_books_to_users where userid=25000000003265 
    union 
    select distinct bookid from db_books_to_teams where teamid in 
     (
      select a.teamid from db_team_users a 
      inner join db_teams b on (b.teamid=a.teamid and b.deleted=0) 
      where a.deleted=0 AND a.userid=25000000003265 
     ) 
    ) 
) 
group by db_books.bookid 
limit 20 

解釋計劃如下。

id select_type table type possible_keys key key_len ref rows Extra 
1 PRIMARY sender_user ALL PRIMARY,u2    14573 Using where; Using temporary; Using filesort 
1 PRIMARY db_books ref i_db_books_target_company_id,i_db_books_sndrUserid,i_db_books_sndrCompanyid,i_sndrUserid_sender_team_idbookid i_db_books_sndrUserid 7 mde_staging.sender_user.uid 41 Using where 
1 PRIMARY sender_company eq_ref PRIMARY,db_companies_icd PRIMARY 7 mde_staging.db_books.sndrCompanyid 1 Using where 
1 PRIMARY receiver_company eq_ref PRIMARY,db_companies_icd PRIMARY 7 mde_staging.db_books.target_company_id 1 Using where 
1 PRIMARY sender_team_id eq_ref PRIMARY,db_teams_i PRIMARY 7 mde_staging.db_books.sender_team_id 1 
1 PRIMARY receiver_user ref i_db_books_to_users_bookid i_db_books_to_users_bookid 7 mde_staging.db_books.bookid 1 
1 PRIMARY receiver_user_details eq_ref PRIMARY,u2 PRIMARY 7 mde_staging.receiver_user.userid 1 
1 PRIMARY receiver_teams ref i_db_books_to_teams_bookid i_db_books_to_teams_bookid 7 mde_staging.db_books.bookid 1 
1 PRIMARY receiver_team_details eq_ref PRIMARY,db_teams_i PRIMARY 7 mde_staging.receiver_teams.teamid 1 
1 PRIMARY status eq_ref PRIMARY PRIMARY 4 mde_staging.db_books.statusid 1 
1 PRIMARY state eq_ref PRIMARY PRIMARY 4 mde_staging.db_books.request_state_id 1 
1 PRIMARY purpose eq_ref PRIMARY PRIMARY 4 mde_staging.db_books.request_purpose_id 1 
1 PRIMARY assignee eq_ref PRIMARY,u2 PRIMARY 7 mde_staging.db_books.assignee 1 
1 PRIMARY mdtl ref db_books_details_bookid db_books_details_bookid 7 mde_staging.db_books.bookid 1 
1 PRIMARY request_type ALL PRIMARY    4 Using where; Using join buffer 
1 PRIMARY g eq_ref PRIMARY,db_entities7 PRIMARY 7 mde_staging.mdtl.entityid 1 
3 DEPENDENT SUBQUERY db_books_to_users ref i_db_books_to_users_bookid i_db_books_to_users_bookid 7 func 1 Using where; Using temporary 
4 DEPENDENT UNION db_books_to_teams ref i_db_books_to_teams_bookid i_db_books_to_teams_bookid 7 func 1 Using where; Using temporary 
5 DEPENDENT SUBQUERY b eq_ref PRIMARY,db_teams_i PRIMARY 7 func 1 Using where 
5 DEPENDENT SUBQUERY a ref db_team_users_i db_team_users_i 11 func,const 1 Using where 
    UNION RESULT <union3,4> ALL      
2 DEPENDENT SUBQUERY b eq_ref PRIMARY,db_teams_i PRIMARY 7 func 1 Using where 
2 DEPENDENT SUBQUERY a ref db_team_users_i db_team_users_i 7 func 1 Using where 

如果你看到解釋計劃的第一行,它不使用可能的索引,然後使用文件排序等,不知道是否這就是問題所在。請建議我如何解決這個或我使用什麼索引?

回答

0

我看到的最大問題是子查詢限定符。每行測試的打擊次數。然後,我會將WHERE子句部分更改爲第一個表的預查詢語言,並將所得到的書籍和書籍連接起來,其餘部分應該沒問題。另外,條款「STRAIGHT_JOIN」告訴引擎按照你所說的順序進行查詢。有時候,它會超越你,並試圖根據其中一個「查找」參考表進行優化,而回填找到其餘的。所有這一切說,

改變選擇在頂部

select STRAIGHT_JOIN distinct 

,然後你的FROM子句從

from 
     db_books db_books 

from 
     (SELECT distinct db.bookid 
      from 
       db_books db 
       left join db_team_users TeamA 
        ON db.sndrUserID = TeamA.userID 
        AND db.Sender_Team_ID = TeamA.TeamID 
        LEFT JOIN db_teams TeamB 
         ON TeamA.TeamID = TeamB.TeamID 
         AND TeamB.Deleted = 0 
       left join db_books_to_users ToUser 
        ON db.BookID = ToUser.BookID 
        AND db.sndrUserID = ToUser.userID 
       left join db_books_to_teams ToTeamA 
        ON db.TeamID = ToTeamA.TeamID 
        AND db.sndrUserID = ToTeamA.UserID 
        AND a.Deleted = 0 
        left join db_teams ToTeamsB 
         ON ToTeamA.TeamID = ToTeamB.TeamID 
         AND b.Deleted = 0 
      where 
       db.sndrUserID = 25000000003265 
       OR NOT TeamB.TeamID IS NULL 
       OR NOT ToUser.BookID IS NULL 
       OR NOT ToTeamB.TeamID IS NULL 
      limit 
       20) PreQualBooks 
     JOIN db_books 
     ON PreQualBooks.BookID = db_Books.BookID 

而且你可以刪除決賽,因爲此預先查詢將在一次前完成,以基於用戶或團隊預先確定每個POSSIBLE圖書ID與JOIN的關係。通過允許LEFT JOIN,書籍表經歷ONCE,具有與團隊/用戶狀態相關的所有關係,並且將僅基於發送用戶或相應LEFT JOIN(TeamB,ToUser和ToTeamB)的最低級別返回這些記錄。這種預先查詢也適用於20本書的限制,所以在查詢結束時不需要LIMIT子句,因爲只有20本書是可能的。

由於您的group_concat,請留下您的Outer GROUP BY。