1

I would like to know if there is a way to optimize this query :

SELECT
    jdc_organizations_activities.*,
    jdc_organizations.orgName, 
    CONCAT(jos_hpj_users.firstName, ' ', jos_hpj_users.lastName) AS nameContact  
FROM jdc_organizations_activities
LEFT JOIN jdc_organizations ON jdc_organizations_activities.organizationId =jdc_organizations.id
LEFT JOIN jos_hpj_users ON jdc_organizations_activities.contact = jos_hpj_users.userId
WHERE jdc_organizations_activities.status LIKE 'proposed'  
ORDER BY jdc_organizations_activities.creationDate DESC LIMIT 0 , 100 ;

Tables Info

Now When i see the query log :

 Query_time: 2  
 Lock_time: 0  
 Rows_sent: 100  
 Rows_examined: **1028330**

Query Profile :

enter image description here

2) Should i put indexes on the tables having in mind that there will be a lot of inserts and updates on those tables .

From Tizag Tutorials :

Indexes are something extra that you can enable on your MySQL tables to increase performance,cbut they do have some downsides. When you create a new index MySQL builds a separate block of information that needs to be updated every time there are changes made to the table. This means that if you are constantly updating, inserting and removing entries in your table this could have a negative impact on performance.

Update after adding indexes and removing the lower() , group by and the wildcard

Time: 0.855ms

enter image description here

4

4 回答 4

4

在以下位置添加索引(如果没有):

表:jdc_organizations_activities

  • 简单的索引creationDate
  • 简单的索引status
  • 简单的索引organizationId
  • 简单的索引contact

并通过删除对函数的调用LOWER()并使用=or来重写查询LIKE。这取决于您为此表定义的排序规则,但如果它是不区分大小写的排序规则(如latin1),它仍然会显示相同的结果。详细信息可以在MySQL 文档中找到:case-sensitive

SELECT a.*
     , o.orgName
     , CONCAT(u.firstName,' ',u.lastName) AS nameContact  

FROM jdc_organizations_activities AS a
  LEFT JOIN jdc_organizations AS o
    ON a.organizationId = o.id 
  LEFT JOIN jos_hpj_users AS u
    ON a.contact = u.userId

WHERE a.status LIKE 'proposed'     --- or (a.status = 'proposed')

ORDER BY a.creationDate DESC 
LIMIT 0 , 100 ;

如果您发布执行计划(就像现在一样)并在这些更改之后发布,那就太好了。


更新

对于此查询,复合索引(status, creationDate)可能更合适(如 Darhazer 建议的那样),而不是简单的(status). 但这是更多的猜测工作。发布计划(运行后EXPLAIN query)将提供更多信息。

我还假设您已经有(主键)索引:

  • jdc_organizations.id
  • jos_hpj_users.userId
于 2011-07-04T12:17:30.977 回答
2

从 EXPLAIN 发布结果 通常,您需要 .status 和 .status 上jdc_organizations_activities.organizationIdjdc_organizations_activities.contact复合索引jdc_organizations_activitiesjdc_organizations_activities.creationDate

为什么您使用 LIKE 查询进行常量查找(您没有通配符,或者您可能已编辑查询)状态索引可用于 LIKE 'proposed%' 但不能用于 LIKE '%proposed% ' - 在后一种情况下,最好只在 creationDate 上留下索引

于 2011-07-04T11:48:22.573 回答
1

缓慢是因为 mysql 必须适用lower()每一行。解决方案是创建一个新列来存储 lower 的结果,然后在该列上放置一个索引。让我们也使用触发器来使解决方案更加豪华。好的,我们开始:

a) 添加一个新列来保存较低版本的状态(使这个 varchar 与状态一样宽):

ALTER TABLE jdc_organizations_activities ADD COLUMN status_lower varchar(20);

b) 填充新列:

UPDATE jdc_organizations_activities SET status_lower = lower(status);

c) 在新列上创建索引

CREATE INDEX jdc_organizations_activities_status_lower_index
    ON jdc_organizations_activities(status_lower);

d) 定义触发器以保持新列值正确:

DELIMITER ~;
CREATE TRIGGER jdc_organizations_activities_status_insert_trig
BEFORE INSERT ON jdc_organizations_activities
FOR EACH ROW
BEGIN
    NEW.status_lower = lower(NEW.status);
END;

CREATE TRIGGER jdc_organizations_activities_status_update_trig
BEFORE UPDATE ON jdc_organizations_activities
FOR EACH ROW
BEGIN
    NEW.status_lower = lower(NEW.status);
END;~
DELIMITER ;

您的查询现在应该会飞。

于 2011-07-04T12:29:24.193 回答
1

这些表上有哪些索引?具体来说,您是否为 jdc_organizations_activities.creationDate 编制了索引?

另外,为什么需要按 jdc_organizations_activities.id 分组?这不是每行唯一的,还是一个组织可以有多个联系人?

于 2011-06-30T18:27:27.070 回答