2017-09-13 40 views
0

與正在20秒返回結果:(發送數據的時間太長,但指標AREADY創建

在表案件和cases_cstm查詢我有問題,我有96萬行

這是我的查詢:

SELECT cases.id ,cases_cstm.assunto_c, cases.name , cases.case_number , 
     cases.priority , accounts.name account_name , 
     accounts.assigned_user_id account_name_owner , 
     'Accounts' account_name_mod, cases.account_id , 
     LTRIM(RTRIM(CONCAT(IFNULL(jt1.first_name,''),' ',IFNULL(jt1.last_name,'')))) assigned_user_name , 
     jt1.created_by assigned_user_name_owner , 
     'Users' assigned_user_name_mod, cases.status , cases.date_entered , 
     cases.assigned_user_id 
    FROM cases 
    LEFT JOIN cases_cstm ON cases.id = cases_cstm.id_c 
    LEFT JOIN accounts accounts ON 
     cases.account_id=accounts.id AND accounts.deleted=0 AND 
     accounts.deleted=0 
    LEFT JOIN users jt1 ON 
     cases.assigned_user_id=jt1.id AND 
     jt1.deleted=0 AND jt1.deleted=0 
    where 
    (((LTRIM(RTRIM(CONCAT(IFNULL(accounts.name,'')))) LIKE 'rodrigo fernando%' OR 
    LTRIM(RTRIM(CONCAT(IFNULL(accounts.name,'')))) LIKE 'rodrigo fernando%'))) AND 
    cases.deleted=0 ORDER BY cases.date_entered DESC LIMIT 0,11; 

這裏是表的索引:

+-------+------------+--------------------+--------------+------------------ 
+-----------+-------------+----------+--------+------+------------+-------- 
| Table | Non_unique | Key_name   | Seq_in_index | Column_name |Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment 
+-------+------------+--------------------+--------------+------------------ 
+-----------+-------------+----------+--------+------+------------+--------- 
| cases |   0 | PRIMARY   |   1 | id   | A   |  911472 |  NULL | NULL |  | BTREE  |   
| cases |   0 | case_number  |   1 | case_number | A   |  911472 |  NULL | NULL |  | BTREE  |   
| 
| cases |   1 | idx_case_name  |   1 | name  | A   |  911472 |  NULL | NULL | YES | BTREE  |   
| 
| cases |   1 | idx_account_id  |   1 | account_id | A   |  455736 |  NULL | NULL | YES | BTREE  |   
| 
| cases |   1 | idx_cases_stat_del |   1 | assigned_user_id| A   |   106 |  NULL | NULL | YES | BTREE  |   
| 
| cases |   1 | idx_cases_stat_del |   2 | status  | A   |   197 |  NULL | NULL | YES | BTREE  |   
| 
| cases |   1 | idx_cases_stat_del |   3 | deleted  | A   |   214 |  NULL | NULL | YES | BTREE  |   
| 
| cases |   1 | idx_priority  |   1 | priority | A   |  455736 |  NULL | NULL | YES | BTREE  |   
| 
| cases |   1 | idx_date_entered |   1 | date_entered| A   |  455736 |  NULL | NULL | YES | BTREE  |   
+-------+------------+--------------------+--------------+------------------ 
+-----------+-------------+----------+--------+------+------------+--------- 

The Explain command of query(Image!)

這是查詢執行的個人資料:

+--------------------+-----------+ 
| Status    | Duration | 
+--------------------+-----------+ 
| starting   | 0.000122 | 
| Opening tables  | 0.000180 | 
| System lock  | 0.000005 | 
| Table lock   | 0.000005 | 
| init    | 0.000051 | 
| optimizing   | 0.000017 | 
| statistics   | 0.000071 | 
| preparing   | 0.000021 | 
| executing   | 0.000003 | 
| Sorting result  | 0.000004 | 
| Sending data  | 21.595455 | 
| end    | 0.000012 | 
| query end   | 0.000002 | 
| freeing items  | 0.000419 | 
| logging slow query | 0.000005 | 
| logging slow query | 0.000002 | 
| cleaning up  | 0.000004 | 

有人可以幫助我undertang爲什麼查詢花費這麼長時間來執行呢?

謝謝!

+0

你有很多的函數調用where子句,可能是這個問題 – blueCat

+0

像往常一樣,Profile說無用的「發送數據」。 –

+0

這不應該花20秒。其他事情正在發生。請提供'SHOW CREATE TABLE cases'。 –

回答

0

首先,你LEFT JOIN改變賬戶的INNER JOIN我不知道這是否會做大的改變,但是如果你瞭解其中的差異,它會更有意義。

你在說什麼LEFT JOIN是「我想要所有的情況下,不管他們有沒有關聯的帳戶」。這裏的INNER JOIN的意思是「給我所有的案件,並返回所有的帳戶」。

查詢的最終結果是一樣的,因爲你是以後的事情濾波與你的WHERE條款,但我有一種感覺,這可能爲什麼idx_account_id被忽略。

第二,可能更大的問題是你的where子句:

(((LTRIM(RTRIM(CONCAT(IFNULL(accounts.name,'')))) LIKE 'rodrigo fernando%' OR 
LTRIM(RTRIM(CONCAT(IFNULL(accounts.name,'')))) LIKE 'rodrigo fernando%'))) AND 

有一噸的功能,在這裏,和MySQL無法優化使用索引。每條記錄都將檢查此條件,並且您正在使用的所有功能都將針對每條記錄進行調用。這很可能是最大的問題。

首先,這可以簡化一下。我覺得這樣或聲明雙方都是一樣的,所以讓我們首先把它變成一個:

LTRIM(RTRIM(CONCAT(IFNULL(accounts.name,'')))) LIKE 'rodrigo fernando%' 

因爲你是在switch語句的一側添加一個通配符,爲什麼與RTRIM麻煩?

LTRIM(CONCAT(IFNULL(accounts.name,''))) LIKE 'rodrigo fernando%' 

如果只有一件事,你不需要CONCAT任何東西!

LTRIM(IFNULL(accounts.name,'')) LIKE 'rodrigo fernando%' 

LTRIM工作在NULL就好值

LTRIM(accounts.name) LIKE 'rodrigo fernando%' 

好吧,這爲我們節省了一堆功能。然而,最後一個LTRIM仍然是一個主要問題,因爲它完全仍然阻止使用索引的mysql。解決的方法是相當簡單的,但:

  1. 更新您的帳戶表,一旦:

    UPDATE帳戶上設置名稱= LTRIM(名);

  2. 確保無論何時插入新帳戶,您都需要在插入之前進行修剪。所以你現在在INSERT時間內這樣做,而不是SELECT時間。

  3. 改變你以前的WHERE子句:

    accounts.name LIKE '羅德里戈費爾南多%'

繁榮,現在還可以accounts.name使用索引,這將是快他媽的。

+0

是的,這個工程!我現在要做的就是改變內部聯接,在case_cstm和個案到帳戶和查詢現在執行0.9秒的情況下。 感謝您的幫助 –

+0

然後你應該接受我的答案! – Evert

0

您需要更改查詢以及索引。由於您僅在個案表上編入索引,並且您正在使用帳戶和用戶表,因此您應該在編制索引時考慮這些表。按以下方式在您的查詢中進行更改。

SELECT cases.id, cases_cstm.assunto_c, cases.name, cases.case_number, cases.priority, accounts.name account_name, accounts.assigned_user_id account_name_owner, 'Accounts' account_name_mod, cases.account_id, LTRIM(RTRIM(CONCAT(IFNULL(jt1.first_name,''),' ',IFNULL(jt1.last_name,'')))) assigned_user_name, jt1.created_by assigned_user_name_owner,'Users' assigned_user_name_mod, cases.status, cases.date_entered, cases.assigned_user_id FROM cases [enter link description here][1] LEFT JOIN cases_cstm ON cases.id = cases_cstm.id_c LEFT JOIN accounts accounts ON cases.account_id=accounts.id AND accounts.deleted=0 AND (TRIM(accounts.name) LIKE 'rodrigo fernando%' OR TRIM(accounts.name) LIKE 'rodrigo fernando%') LEFT JOIN users jt1 ON cases.assigned_user_id=jt1.id AND jt1.deleted=0 WHERE cases.deleted=0 ORDER BY cases.date_entered DESC LIMIT 0,11;

然後第一刪除沒有被使用,那麼創建表的索引的索引如下:

  1. 案例 - 刪除,date_entered(一個具有多個列索引)
  2. 帳戶 - 刪除,名稱(多列索引)
  3. 用戶 - 刪除

創建這些索引並確保查詢中選定和使用的列的順序必須相同,因爲MySql使用索引的最左邊的前綴。如果你需要更多信息,請到通過這些鏈接:

0

我能解決這個問題後,Evert的提示! 要清楚,這是一個由系統動態安裝的查詢,我仍然需要優化代碼以刪除在這種情況下沒有意義的功能。 對我有什麼幫助的是,在case_cstm和accounts的情況下,用INNER替換LEFT ......只有這個改變,查詢纔開始在0.9秒內執行!

感謝大家的幫助!