簡體   English   中英

如何使此查詢運行得更快?

[英]How would I make this query run faster?

我怎樣才能使這個查詢運行得更快......?

SELECT    account_id, 
          account_name, 
          account_update, 
          account_sold, 
          account_mds, 
          ftp_url,         
          ftp_livestatus, 
          number_digits, 
          number_cw,
          client_name, 
          ppc_status, 
          user_name 
FROM     
         Accounts, 
         FTPDetails, 
         SiteNumbers, 
         Clients, 
         PPC, 
         Users 

WHERE    Accounts.account_id = FTPDetails.ftp_accountid 
AND      Accounts.account_id = SiteNumbers.number_accountid 
AND      Accounts.account_client = Clients.client_id     
AND      Accounts.account_id = PPC.ppc_accountid 
AND      Accounts.account_designer = Users.user_id   
AND      Accounts.account_active = 'active' 
AND      FTPDetails.ftp_active = 'active' 
AND      SiteNumbers.number_active = 'active' 
AND      Clients.client_active = 'active'    
AND      PPC.ppc_active = 'active'   
AND      Users.user_active = 'active' 
ORDER BY 
         Accounts.account_update DESC

提前致謝:)

解釋查詢結果:

表的第一部分

表的第二部分

我真的沒有設置任何外鍵...我試圖避免對數據庫進行更改,因為很快就必須進行全面檢修。

只有主鍵是每個表的 id,例如 account_id、ftp_id、ppc_id...

索引

  • 您需要 -至少- 在JOIN條件中使用的每個字段的索引。

  • 出現在WHEREGROUP BYORDER BY子句中的字段索引在大多數情況下也很有用。

  • 當在一個表中,兩個或多個字段用於 JOIn(或 WHERE 或 GROUP BY 或 ORDER BY)時,這些(兩個或多個)字段的復合(組合)索引可能比單獨的索引更好。 例如,在SiteNumbers表中,可能的索引是復合(number_accountid, number_active)(number_active, number_accountid)

  • Boolean(開/關,活動/非活動)字段中的條件有時會減慢查詢速度(因為索引不是選擇性的,因此不是很有幫助)。 在這種情況下,重組(父親規范化)表是一種選擇,但您可能可以避免增加的復雜性。


除了通常的建議(檢查 EXPLAIN 計划,在需要的地方添加索引,測試查詢的變體),

我注意到在您的查詢中有一個部分笛卡爾積。 Accounts與三個表FTPDetailsSiteNumbersPPC具有一對多的關系。 例如,如果您有 1000 個帳戶,並且每個帳戶都與 10 個 FTPDetails、20 個 SiteNumbers 和 3 個 PPC 相關,則查詢將為每個帳戶返回 600 行(10x20x3 的乘積)。 總共有 600K 行,其中重復了許多數據。

您可以將查詢拆分為三加一以獲取基本數據(帳戶和 rest 表)。 這樣,只會傳輸 34K 行數據(長度更短):

Accounts JOIN Clients JOIN Users 
  (with all fields needed from these tables)
  1K rows

Accounts JOIN FTPDetails
  (with Accounts.account_id and all fields from FTPDetails)
  10K rows

Accounts JOIN SiteNumbers
  (with Accounts.account_id and all fields from SiteNumbers)
  20K rows

Accounts JOIN PPC
  (with Accounts.account_id and all fields from PPC)
  3K rows

然后在客戶端使用來自 4 個查詢的數據來顯示組合信息。



我會添加以下索引:

Table Accounts
  index on (account_designer)
  index on (account_client)
  index on (account_active, account_id)
  index on (account_update)

Table FTPDetails
  index on (ftp_active, ftp_accountid)

Table SiteNumbers
  index on (number_active, number_accountid)

Table PPC
  index on (ppc_active, ppc_accountid)

使用EXPLAIN找出可以使用的索引以及實際使用的索引。 如有必要,創建適當的索引。

如果FTPDetails.ftp_active只有兩個有效條目'active''inactive' ,則使用BOOL作為數據類型。

作為旁注:我強烈建議使用顯式連接而不是隱式連接:

SELECT
  account_id, account_name, account_update, account_sold, account_mds, 
  ftp_url, ftp_livestatus, 
  number_digits, number_cw,
  client_name, 
  ppc_status, 
  user_name 
FROM Accounts 
INNER JOIN FTPDetails
  ON  Accounts.account_id = FTPDetails.ftp_accountid
  AND FTPDetails.ftp_active = 'active'
INNER JOIN SiteNumbers
  ON  Accounts.account_id = SiteNumbers.number_accountid 
  AND SiteNumbers.number_active = 'active'
INNER JOIN Clients
  ON  Accounts.account_client = Clients.client_id
  AND Clients.client_active = 'active'
INNER JOIN PPC
  ON  Accounts.account_id = PPC.ppc_accountid
  AND PPC.ppc_active = 'active'
INNER JOIN Users
  ON  Accounts.account_designer = Users.user_id
  AND Users.user_active = 'active'
WHERE Accounts.account_active = 'active' 
ORDER BY Accounts.account_update DESC

這使得查詢更具可讀性,因為連接條件接近正在連接的表的名稱。

解釋,對不同的選項進行基准測試。 對於初學者,我確信有幾個查詢會比這個怪物更快。 首先,因為查詢優化器將花費大量時間檢查最佳連接順序(5.=120 種可能性),其次,像SELECT... WHERE....active = 'active'這樣的查詢將被緩存(盡管這取決於數據更改的數量)。

您的主要問題之一在這里: x.y_active = 'active'

問題:基數低
活動字段是具有 2 個可能值的 boolean 字段,因此它的基數非常低。 MySQL(或任何 SQL 在 30% 或更多的行具有相同值時不會使用索引)。
強制索引是無用的,因為它會使您的查詢變慢,而不是更快。

解決方案:對表進行分區
一種解決方案是在active列上對表進行分區。
這將排除所有非活動字段,並使select的行為就像您實際上在xxx-active字段上有一個工作索引一樣。

邊注
請永遠不要使用隱式where連接,它太容易出錯並且無法使用。
請改用Oswald's answer 之類的語法。

鏈接:
基數: http://en.wikipedia.org/wiki/Cardinality_(SQL_statements)
基數和索引: http://www.bennadel.com/blog/1424-Exploring-The-Cardinality-And-Selectivity-Of-SQL-Conditions.htm
MySQL 分區: http://dev.mysql.com/doc/refman/5.5/en/partitioning.ZDFC35FDC70D2E298

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM