背景: 具有字段 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/