我想知道是否有人可以解释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
答案 0 :(得分:1)
date_created
数据类型需要更改为DATETIME才值得在列上定义索引。原因是,如果您正在将数据类型从字符串更改为DATETIME,那么索引将毫无价值。
您已经提到过您正在使用LOAD DATA INFILE
,并且源文件包含DD-MON-YY格式的日期。 MySQL will implicitly convert strings into DATETIME if the YY-MM-DD format is used,因此如果您在使用LOAD DATA INFILE
之前可以在源文件中更正此内容,则其他内容应该放在原位。
之后,covering index使用:
......会是一个好主意。
答案 1 :(得分: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'
如果使用列
上的函数,有时不会使用索引答案 2 :(得分:0)
我的建议是用JOIN替换IN,然后考虑在某些列上添加索引,例如作业,可能还有操作和/或结果。您应该阅读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';