Mysql 查询之间的性能较差
我正在尝试使用此查询在多个时段之间查找个人的考试结果:Mysql 查询之间的性能较差,mysql,sql,performance,indexing,between,Mysql,Sql,Performance,Indexing,Between,我正在尝试使用此查询在多个时段之间查找个人的考试结果: SELECT * FROM RESULTS AS R, Define_Times AS T WHERE R.PERSONID = T.PERSONID AND ( (R.DATE BETWEEN T.Previous_Month_Start AND T.Previous_Month_End) OR (R.DATE BETWEEN T.Next_Month_Start AND T.Next_Month_End) OR (R.DATE
SELECT * FROM RESULTS AS R, Define_Times AS T
WHERE R.PERSONID = T.PERSONID AND (
(R.DATE BETWEEN T.Previous_Month_Start AND T.Previous_Month_End) OR
(R.DATE BETWEEN T.Next_Month_Start AND T.Next_Month_End) OR
(R.DATE BETWEEN T.Six_Month_Start AND T.Six_Month_End) OR
(R.DATE BETWEEN T.One_Year_Start AND T.One_Year_End) OR
(R.DATE BETWEEN T.Two_Year_Start AND T.Two_Year_End) OR
(R.DATE BETWEEN T.Three_Year_Start AND T.Three_Year_End) OR
(R.DATE BETWEEN T.Four_Year_Start AND T.Four_Year_End) )
每个人的上一年/下一年/一年等各不相同
解释给出:
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | T | ALL | PEOPLE | NULL | NULL | NULL | 75775 | |
| 1 | SIMPLE | R | ref | IDX3,IDX2 | IDX3 | 5 | T.PERSONID | 3550 | Using where |
结果表大约有3亿行。定义_次有75000次
要花很长时间
我看到第一种类型是所有,这是坏的。但如果情况如此糟糕,为什么不使用它认为可能的PERSONID(称为PEOPLE)索引呢?我能做些什么来改进这一点
我也看不到它使用的日期索引-有一个在R.date。(这是索引IDX2上5的序列中的第一个。)
抱歉输入错误-我的键盘坏了,请提前感谢。作为比较,您能运行此等效查询吗
SELECT * FROM Define_Times AS T
INNER JOIN RESULTS AS R on
(R.PERSONID = T.PERSONID and
(
(R.DATE BETWEEN T.Previous_Month_Start AND T.Previous_Month_End) OR
(R.DATE BETWEEN T.Next_Month_Start AND T.Next_Month_End) OR
(R.DATE BETWEEN T.Six_Month_Start AND T.Six_Month_End) OR
(R.DATE BETWEEN T.One_Year_Start AND T.One_Year_End) OR
(R.DATE BETWEEN T.Two_Year_Start AND T.Two_Year_End) OR
(R.DATE BETWEEN T.Three_Year_Start AND T.Three_Year_End) OR
(R.DATE BETWEEN T.Four_Year_Start AND T.Four_Year_End)
)
)
我看到优化器在这种形式下有时工作得更好
此外,由于您或所有的date-between表达式,它几乎无法使用日期索引,因为任何日期范围都可以满足where子句
编辑--添加
如果您不想运行查询,请至少尝试比较估计的执行计划问题在于所有条件都在一起 如果可能,请重新构造数据库,使Define_Time只有四列:
CREATE TABLE Define_Times (
PersonID INTEGER,
PeriodType SomeType,
StartDate DATE,
EndDate DATE )
然后,每个人都会得到7条记录(或者更多,如果您的示例中没有搜索更多的时段),其中PeriodType指示日期指定的时段(您可以使用诸如PM、NM、SM、1Y、2Y、3Y、4Y之类的文本值,也可以使用指向另一个表中描述的整数值)
然后,按如下方式重写查询:
SELECT * FROM RESULTS AS R, Define_Times AS T
WHERE R.PERSONID = T.PERSONID
AND R.DATE BETWEEN T.StartDate AND T.EndDate
AND T.PeriodType IN (PM,NM,SM,1Y,2Y,3Y,4Y)
此查询至少是可优化的
此查询将为每个人的每个匹配期间生成一条记录。如果你的经期没有重叠,那没关系(只有一条匹配的记录)。如果周期重叠,并且每个结果集中只需要一条记录,则需要对结果集中的记录进行DISTINCT或GROUP BY聚合,以完成一些额外的工作
另外,请注意,如果Define_Times表中没有任何额外的句点,则可以删除WHERE子句中的
和t.PeriodType
部分。您是否尝试过使用连接来选择这两个表,只是语义不同而已。Define_Times中的每一行是否都有相应的结果人员?您是否能够重新构造数据库以规范化Define_Times?第一行R.DATE是否正确,或者R.ETRDATE是否拼写错误?因此基本上更改了内部连接的位置?(只是为了确认我没有错过任何东西。)我可以试试——但如果情况没有好转,我们将在一周左右的时间内无法得知!)刚刚看到你的按执行编辑计划,你是说解释?如果是-完全相同.Estimated plan意味着查询没有实际运行,但它提供了实际执行计划的“最佳猜测”。您可能希望这样做来查询长时间运行的替代方案,您不希望在数据库上运行。不要运行足够多的MySql来回忆这是否是一个选项——在工作中,MySql无法进行双重检查。酷-我会尝试一下,让你知道。谢谢我需要一个特定的索引来利用这个新查询吗?在表结果上以(PersonID,Date)开头的索引将是最佳的优化方法。我不是MySQL专家,所以不知道它会如何优化这个查询,但至少它有可能进行优化。