优化MySql查询

时间:2011-06-30 18:08:49

标签: mysql performance query-optimization sql-optimization

我想知道是否有办法优化此查询:

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

现在当我看到查询日志时:

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

查询个人资料:

enter image description here

2)我应该在表上放置索引,记住这些表上会有很多插入和更新。

来自Tizag教程:

  

索引是你的另外一点   可以在你的MySQL表上启用   提高性能,但他们确实有   一些缺点。当你创建一个新的   索引MySQL构建一个单独的块   需要更新的信息   每次都有变化   桌子。 这意味着如果你   不断更新,插入和   删除表中的条目   可能会对...产生负面影响   性能

添加索引并删除lower(),group by和通配符

后更新

时间: 0.855ms

enter image description here

4 个答案:

答案 0 :(得分:4)

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

表:jdc_organizations_activities

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

通过删除对函数LOWER()的调用并使用=LIKE来重写查询。它取决于您为此表定义的排序规则,但如果它不区分大小写(如latin1),它仍会显示相同的结果。有关详细信息,请访问 MySQL docs: case-sensitivity

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

答案 1 :(得分:2)

发布EXPLAIN的结果 通常,您需要jdc_organizations_activities.organizationIdjdc_organizations_activities.contact上的索引,jdc_organizations_activities上的综合索引。状态和jdc_organizations_activities.creationDate

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

答案 2 :(得分:1)

您对这些表有哪些索引?具体来说,您是否已将jdc_organizations_activities.creationDate?

编入索引

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

答案 3 :(得分: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 ;

您的查询现在应该飞。