0

我想知道是否有人可以解释 IN 是如何计算的?好吧,最终我试图找出为什么这个查询很慢以及如何优化它。我等了 3 多分钟,当我取消查询时,它只返回了 1000 行,这似乎不需要那么长时间。

SELECT t2.* 
FROM report_tables.roc_test_results as t2 
WHERE t2.job IN (SELECT DISTINCT(t1.job) 
                   FROM report_tables.roc_test_results as t1 
                  WHERE t1.operation = 'TEST' 
                    AND result = 'Passed' 
                    AND STR_TO_DATE(t1.date_created,'%d-%M-%Y') BETWEEN '2009-10-01' 
                                                                    AND '2009-10-31')

我不确定总查询应该返回什么,如果我不得不猜测我会说大约 2000 条记录,则子查询返回 332(非 Distinct 时为 336)。

谁能给我一些关于如何优化这个查询的指示?另外,我想知道,子查询是每次计算还是只计算一次并存储它?

根据要求,DESC 的结果...(顺便说一句,请不要笑,我是自学成才的,所以我确信这张桌子设计得很糟糕。)

Field                     Type               Null     Key    Default    Extra
------                      -----              -----     ---    -------    -----
operation                 varchar(10)         NO   
tester                 varchar(25)            NO   
result                 varchar(45)            NO   
fail_mode              varchar(45)         NO   
primary_failure        varchar(25)           NO   
ref_des                varchar(45)           NO   
rf_hours               varchar(15)          NO   
ac_hours               varchar(15)          NO   
comments               text              NO   
job                    varchar(15)           NO   
rma                    bigint(20) unsigned    NO   
item                   varchar(45)          NO   
item_description       text                  NO   
serial                 varchar(25)            NO   
created_by             varchar(25)            NO   
collection             bigint(20) unsigned    NO    PRI  
date_created           varchar(15)          NO   
4

3 回答 3

1

date_created值得在列上定义索引之前,数据类型需要更改为 DATETIME。原因是,如果您现在将数据类型从字符串更改为 DATETIME,则索引将毫无价值。

您提到您正在使用LOAD DATA INFILE,并且源文件包含 DD-MON-YY 格式的日期。 如果使用 YY-MM-DD 格式,MySQL 将隐式将字符串转换为 DATETIME,因此如果您可以在使用之前在源文件中更正此问题,LOAD DATA INFILE那么其余的应该就位。

之后,覆盖索引使用:

  • 工作
  • 手术
  • 结果
  • 创建日期

...将是一个好主意。

于 2010-06-04T18:33:05.870 回答
0

首先,您不需要子查询中的 distinct,因为 IN 无论如何都消除了重复项您是否需要 WHERE 子句中的函数调用,并且您在 date_created 列上有索引吗?

当你改变时会发生什么

WHERE STR_TO_DATE(t1.date_created,'%d-%M-%Y') 
BETWEEN '2009-10-01' AND '2009-10-31')

WHERE 1.date_created >= '2009-10-01' 
AND 1.date_created < '2010-01-01'

如果您在列上使用函数,有时不会使用索引

于 2010-06-04T15:40:27.413 回答
0

我的建议是将 IN 替换为 JOIN,然后考虑在某些列上添加索引,例如作业,可能还有操作和/或结果。您应该阅读 MySQL 手册中的索引,以及使用 EXPLAIN 优化查询:

http://dev.mysql.com/doc/refman/5.1/en/indexes.html

http://dev.mysql.com/doc/refman/5.1/en/using-explain.html

这是将 IN 转换为 JOIN 的示例:

SELECT distinct t2.* 
FROM roc_test_results as t2
inner join roc_test_results as t1 on t1.job = t2.job
WHERE t1.operation = 'TEST' 
AND t1.result = 'Passed' 
AND STR_TO_DATE(t1.date_created,'%d-%M-%Y') BETWEEN '2009-10-01' AND '2009-10-31';
于 2010-06-04T16:02:22.430 回答