简体   繁体   English

如何在连接查询轨道 mysql 中包含索引列以提高性能

[英]How to include indexed columns in join query rails mysql to improve performance

It is know that index does not work on date columns if they are mapped with any SQL function on them.众所周知,如果日期列与任何 SQL function 映射,则索引不适用于日期列。

People say, including date column with between cases or <= and >= can give indexed date column to show data based on that index (means performance got improved).人们说,包括案例之间的日期列或<= 和 >=可以提供索引日期列以显示基于该索引的数据(意味着性能得到了提高)。 However, I found that both gives same to same results and apparently no performance taken care of.但是,我发现两者都给出相同的结果,并且显然没有考虑到性能。

How exactly we can minimize the query time if everything is streamlined.如果一切都简化了,我们如何才能最大限度地减少查询时间。 Or any better solution to cope with it?或者有什么更好的解决方案来应对它?

I added index on both project_times.date and project_plans.month我在project_times.dateproject_plans.month添加了索引

Example:例子:

Query 1 without sql functions on columns project_times.date and project_plans.month that returns 87 records but time is huge.查询 1 没有 sql 列project_times.dateproject_plans.month函数返回 87 条记录,但时间很长。 May be or may be not the indexing has done on columns:可能是也可能不是对列进行了索引:

ProjectConsultant Load (1169.8ms)  SELECT DISTINCT `project_consultants`.* FROM
 `project_consultants` LEFT OUTER JOIN `projects` ON `projects`.`id` =
 `project_consultants`.`project_id` LEFT OUTER JOIN `project_times` ON
 `project_times`.`project_id` = `projects`.`id` LEFT OUTER JOIN `project_plans` ON
 `project_plans`.`project_id` = `projects`.`id` WHERE (projects.internal =0 and
 (project_times.date >= '2021-01-01' and project_times.date <= '2021-12-31' or
 project_plans.month >= '2021-01-01' and project_plans.month <= '2021-12-31'))

Query 2 with sql functions on columns project_times.date and project_plans.month like ((extract(year from project_times.date)) and (extract(year from project_plans.month)) that returns 87 records but time is again huge (technically NO indexing is done on columns):在列project_times.dateproject_plans.month上使用 sql 函数查询 2,例如((extract(year from project_times.date))(extract(year from project_plans.month)) ,它返回 87 条记录,但时间又很长(技术上没有索引在列上完成):

ProjectConsultant Load (1342.6ms)  SELECT DISTINCT `project_consultants`.* FROM
 `project_consultants` LEFT OUTER JOIN `projects` ON `projects`.`id` =
 `project_consultants`.`project_id` LEFT OUTER JOIN `project_times` ON
 `project_times`.`project_id` = `projects`.`id` LEFT OUTER JOIN `project_plans` ON
 `project_plans`.`project_id` = `projects`.`id` WHERE (projects.internal =0 and (extract(year
 from project_times.date) ='2021' or extract(year from project_plans.month) ='2021'))

Attached images shows the query plan and explain statements output too.附图还显示了查询计划和解释语句 output。

项目计划表的表结构

项目时间表的表结构

项目顾问表的表结构

查询 1 的查询计划

查询 2 的查询计划

Run those queries with a 2 month range instead of a 12 month range.以 2 个月而不是 12 个月的范围运行这些查询。 Query 1 may start using the indexes.查询 1可能开始使用索引。 This because there is overhead in using an index;这是因为使用索引有开销; so, if it does not provide much benefit (not very selective), it will be eschewed by the Optimizer.因此,如果它没有提供太多好处(不是很有选择性),优化器就会避开它。

Please don't use LEFT unless you need it.除非您需要,否则请不要使用LEFT

Those queries seem to limit the output to projects with times and plans in 2021?这些查询似乎将 output 限制在 2021 年有时间计划的项目? If that was not the intent, please explain.如果这不是本意,请解释。

Query 2 will definitely not use an index because functions, such as EXTRACT , are not "sargeable".查询 2 肯定不会使用索引,因为诸如EXTRACT之类的函数不是“可存储的”。

True;真的; BETWEEN is identical in all respects to >= and <= BETWEEN在所有方面与>=<=相同

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM