我遇到的查询问题需要20秒才能返回结果:(
在table cases和cases_cstm中,我有960,000行
这是我的查询:
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 |
有人可以帮我解决为什么执行这么长时间的查询吗?
谢谢!
答案 0 :(得分: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;
然后首先删除未使用的索引,然后在表上创建索引,如下所示:
创建这些索引并确保在查询中选择和使用的列序列必须相同,因为MySql使用索引的任何最左前缀。如果您需要更多详细信息,请浏览以下链接:
答案 1 :(得分:0)
首先,将您的LEFT JOIN
更改为帐户INNER JOIN
我不知道这是否会发生重大变化,但如果您了解其中的差异会更有意义。< / p>
您对LEFT JOIN
说的是&#34;我想要所有案例,无论他们是否有相关帐户&#34;。 INNER JOIN
在这里表示&#34;给我所有案例并返回所有帐户&#34;。
您的查询的最终结果是相同的,因为您稍后使用WHERE
子句过滤掉了内容,但我感觉这可能为{{em> 1}}被忽略了。
第二个可能更大的问题是你的where子句:
idx_account_id
这里有很多功能,MySQL无法使用索引对其进行优化。将检查每个记录的这种情况,并且将为每条记录调用您正在使用的所有功能。这很可能是最大的问题。
首先,这可以简化一下。我认为这个OR语句的两面都是一样的,所以我们先把它变成一个:
(((LTRIM(RTRIM(CONCAT(IFNULL(accounts.name,'')))) LIKE 'rodrigo fernando%' OR
LTRIM(RTRIM(CONCAT(IFNULL(accounts.name,'')))) LIKE 'rodrigo fernando%'))) AND
由于您在switch语句的一侧添加了通配符,为什么还要使用RTRIM呢?
LTRIM(RTRIM(CONCAT(IFNULL(accounts.name,'')))) LIKE 'rodrigo fernando%'
如果只有一件事,你不需要CONCAT任何东西!
LTRIM(CONCAT(IFNULL(accounts.name,''))) LIKE 'rodrigo fernando%'
LTRIM在NULL值上运行良好
LTRIM(IFNULL(accounts.name,'')) LIKE 'rodrigo fernando%'
好吧,这为我们节省了许多功能。但是,最后一个LTRIM仍然是一个主要问题,因为它完全阻止了mysql使用索引。解决方案很简单:
一次更新您的帐户表:
更新帐户SET name = LTRIM(name);
确保无论何时插入新帐户,都要在插入前进行修剪。因此,您现在LTRIM(accounts.name) LIKE 'rodrigo fernando%'
时间内正在执行此操作,而不是INSERT
时间。
将以前的WHERE子句更改为:
accounts.name LIKE&#39; rodrigo fernando%&#39;
Boom,你现在可以在accounts.name上使用一个索引,它就像他妈的一样快。
答案 2 :(得分:0)
我能够按照Evert的提示解决这个问题! 要清楚,这是一个由系统动态安装的查询,我仍然需要优化代码以删除在这种情况下没有意义的功能。 对于Cases_cstm和帐户案例,有什么帮助我用INNER联接替换LEFT ...只有这个改变才开始在0.9秒内执行查询!
感谢大家的帮助!