我想知道是否有办法优化此查询:
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 ;
现在当我看到查询日志时:
Query_time: 2
Lock_time: 0
Rows_sent: 100
Rows_examined: **1028330**
查询个人资料:
2)我应该在表上放置索引,记住这些表上会有很多插入和更新。
来自Tizag教程:
索引是你的另外一点 可以在你的MySQL表上启用 提高性能,但他们确实有 一些缺点。当你创建一个新的 索引MySQL构建一个单独的块 需要更新的信息 每次都有变化 桌子。 这意味着如果你 不断更新,插入和 删除表中的条目 可能会对...产生负面影响 性能
添加索引并删除lower(),group by和通配符
后更新时间: 0.855ms
答案 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.organizationId
,jdc_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 ;
您的查询现在应该飞。