优化MySql查询

发布于 2024-11-17 17:21:25 字数 1297 浏览 4 评论 0原文

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

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

现在当我看到查询时log:

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

查询配置文件:

在此处输入图像描述

2) 我应该放置索引吗在桌子上考虑到这些表上将会有大量的插入和更新。

来自 Tizag 教程:

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

添加索引并删除 lower() 、 group by 和通配符后更新

时间: 0.855ms

在此处输入图像描述

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

椵侞 2024-11-24 17:21:25

添加索引(如果尚未添加):

Table: jdc_organizations_activities

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

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

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 查询后)将提供更多信息。

我还假设您已经在以下位置拥有(主键)索引:

  • jdc_organizations.id
  • jos_hpj_users.userId

Add indexes (if you haven't) at:

Table: jdc_organizations_activities

  • simple index on creationDate
  • simple index on status
  • simple index on organizationId
  • simple index on contact

And rewrite the query by removing call to function LOWER() and using = or LIKE. It depends on the collation you have defined for this table but if it's a case insensitive one (like latin1), it will still show same results. Details can be found at 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 ;

It would be nice if you posted the execution plan (as it is now) and after these changes.


UPDATE

A compound index on (status, creationDate) may be more appopriate (as Darhazer suggested) for this query, instead of the simple (status). But this is more guess work. Posting the plans (after running EXPLAIN query) would provide more info.

I also assumed that you already have (primary key) indexes on:

  • jdc_organizations.id
  • jos_hpj_users.userId
对不⑦ 2024-11-24 17:21:25

发布 EXPLAIN 的结果
通常,您需要对 jdc_organizations_activities.organizationIdjdc_organizations_activities.contact 建立索引,对 jdc_organizations_activities.status 和 jdc_organizations_activities.creationDate 建立复合索引>

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

Post the result from EXPLAIN
Generally you need indexes on jdc_organizations_activities.organizationId, jdc_organizations_activities.contact, composite index on jdc_organizations_activities.status and jdc_organizations_activities.creationDate

Why you are using LIKE query for constant lookup (you have no wildcard symbols, or maybe you've edited the query)
The index on status can be used for LIKE 'proposed%' but can't be used for LIKE '%proposed%' - in the later case better leave only index on creationDate

平生欢 2024-11-24 17:21:25

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

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

What indexes do you have on these tables? Specifically, have you indexed jdc_organizations_activities.creationDate?

Also, why do you need to group by jdc_organizations_activities.id? Isn't that unique per row, or can an organization have multiple contacts?

没有心的人 2024-11-24 17:21:25

速度慢是因为 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 ;

您的查询现在应该可以运行。

The slowness is because mysql has to apply lower() to every row. The solution is to create a new column to store the result of lower, then put an index on that column. Let's also use a trigger to make the solution more luxurious. OK, here we go:

a) Add a new column to hold the lower version of status (make this varchar as wide as status):

ALTER TABLE jdc_organizations_activities ADD COLUMN status_lower varchar(20);

b) Populate the new column:

UPDATE jdc_organizations_activities SET status_lower = lower(status);

c) Create an index on the new column

CREATE INDEX jdc_organizations_activities_status_lower_index
    ON jdc_organizations_activities(status_lower);

d) Define triggers to keep the new column value correct:

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 ;

Your query should now fly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文