mysql - 强制 MySQL 使用非包含索引来避免表扫描?

标签 mysql indexing

背景: 具有字段 ID AUTO INCREMENT PRIMARY KEY 的巨大表,以及在行插入操作时存储 UNIX 时间戳的另一列时间戳。该时间戳列不在任何索引中,由于性能原因我无法为其编制索引。

情况:我们需要在这个巨大的表中查询特定时间戳值之前过去的行;我们可以发出一个 SELECT 语句并在 WHERE 子句中指定该条件,但这会导致全表扫描,因为时间戳列没有索引。

建议:这两列的性质都是随着插入的每一行而递增:AUTO INCREMENT 列递增,timestamp 列也递增。我可以每次将表分成两个相等数量的行,并检查每个边界的时间戳等,直到我到达一行,然后使用该 ID 对其运行正常的 SELECT

此解决方案的问题:这很难,需要大约 25 个查询才能完成该操作,并且这个数字会随着表的增长而增加。

那么问题来了:可以指示 MySQL 在原子上下文中执行该操作吗?

最佳答案

我会尝试为您的主表构建一个辅助表,以至少作为查询的限制基础。用诸如...之类的东西填充表格(显然,将索引放在日期基础上)

create table DailyStartKey as 
SELECT 
      DATE( FROM_UNIXTIME( YourTimeStampColumn ) ) AS DateBasis,
      min( YourAutoIncColumn ) as FirstPKForDay
   from 
      YourTable
   group by 
      1

然后,您可以预查询此表以获得查询中的最小 PK(如果查找日期范围,则可能是最大值)。为了保持它的维护而不必继续重建它,我会在您的主表中添加一个触发器,以便在尚未插入日期的情况下尝试插入此 DailyStartKey 表。

利用它的查询可能是...

select
      YourTable.*
   from 
      ( select FirstPKForDay
            from DailyStartKey
            where DateBasis = "2011-02-12" ) StartDate,
      ( select FirstPKForDay
            from DailyStartKey
            where DateBasis = "2011-02-25" ) LastDate,
      YourTable
   where
         YourTable.YourAutoIncColumn >= StartDate.FirstPKForDay
     and YourTable.YourAutoIncColumn <= LastDate.FirstPKForDay

编辑以阐明另一个 TRIGGER 实现。

为了防止需要继续查询“DailyStartKey”表,您可以创建另一个表,该表始终只有一个记录,其中包含最后一天创建条目的记录。 (或天/小时,具体取决于您想要的粒度)。

然后,在您的触发器中查看是否需要新条目,只需

Select * from LastDateEntryTable where LastDate = CurrentDate

如果已经找到一个,忽略..否则,触发器应该插入每日 key 表并更新“LastDateEntryTable”。

关于mysql - 强制 MySQL 使用非包含索引来避免表扫描?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5218319/

相关文章:

python - 如何选择n维数组中的值

sql - 我可以使用过滤索引来查询 "recently modified"行吗

mysql外连接在哪里

php - 可以发布我的 PHP 和 mySQL 登录脚本以供审查和改进吗?

python - Pandas :更改列中 bool 索引选择的值而不会收到警告

mysql - InnoDB 和 UTF-8 索引的 vachar 最大长度

mysql - 如何在Laravel 5中处理BIT数据类型?

python - MySQL 连接器/Python 存储过程插入未提交

mysql - Mysql中的子查询

oracle - 在空表中执行缓慢的查询。 (删除大量插入后)