2

我有一个包含数百万行的表,包括一个 DATE 和一个 TIME 列。

更改表结构不是一种选择,但可以添加新索引。

考虑到这个查询:

SELECT * FROM Table WHERE TIMESTAMP(Date, Time) BETWEEN 'X' AND 'Y';

我在日期和时间列上有索引,在日期和时间列上也有索引,但是当我使用 TIMESTAMP 函数时,查询不使用索引。

问题是,我可以创建一个使用 TIMESTAMP 函数(不是数据类型)的索引。如果没有,有没有办法可以更改上面的查询以使用索引?

我试图保持查询的简洁和简短,并尽可能避免遍历每个日期。

编辑:

那么,由于 MySQL 不支持表达式索引,有没有办法可以更改此查询以使用日期或(日期,时间)索引?

4

2 回答 2

4

这称为表达式索引,但并非所有 RDBMS 品牌都支持这一点。

你不能在 MySQL 中做到这一点。

最接近的是持久虚拟列,它在 MySQL 的一个分支 MariaDB 中得到支持。但是如果你不能改变你的模式,我想切换到另一个 RDBMS 包也是不可能的。

PostgreSQL 是一个支持表达式索引的 RDBMS 示例。


作为一种解决方法,我建议仅在您的日期列上进行过滤,如果您在该列上有索引,这应该会显着缩小搜索范围。

SELECT * FROM Table WHERE Date BETWEEN 'Xdate' AND 'Ydate' 
  AND CASE WHEN Date = 'Xdate' THEN TIMESTAMP(Date, Time) >= 'X' 
           WHEN Date = 'Ydate' THEN TIMESTAMP(Date, Time) <= 'Y'
           ELSE 1 END;

然后 TIMESTAMP() 表达式只需要针对数据的子集进行评估,而不是整个表中的每一行。在我上面显示的示例中,它只会评估 TIMESTAMP() 如果日期匹配日期范围的开始或结束。如果 Xdate 和 Ydate 之间的日期范围很长并且会匹配很多行,这可能会很有用。无需为中间的所有日期运行该函数。

我没有测试过上面的表达,所以如果我有什么不对劲,我很抱歉,我认为你应该明白这一点。

于 2013-04-17T00:19:13.580 回答
2

我的建议是重写查询以反转函数以仅从 X 和 Y 时间戳生成日期和时间:

SELECT * 
FROM Table 
WHERE (Date, Time) >= ('Xdate', 'Xtime') 
  AND (Date, Time) <= ('Ydate', 'Ytime') ;

正如@BillKarwin 在评论中所解释的那样,这不会从索引中受益。所以,然后重写它,以便(Date, Time)可以使用索引:

SELECT * 
FROM Table 
WHERE 'Xdate' = 'Ydate'
          AND Date = 'Xdate' AND Time >= 'Xtime' AND Time <= 'Ytime'
   OR 'Xdate' < 'Ydate'
          AND ( Date = 'Xdate' AND Time >= 'Xtime'
             OR Date > 'Xdate' AND Date < 'Ydate'
             OR Date = 'Ydate' AND Time <= 'Ytime'
              ) ;

这样,根本不需要调用TIMESTAMP()函数。

于 2013-04-17T00:49:35.943 回答