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专家,所以不知道它会如何优化这个查询,但至少它有可能进行优化。