我有一个表,当前有大约8000万行,创建方式如下:
SELECT
records.id
FROM records
WHERE
(records.status = 0 OR records.status = -10)
AND records.created BETWEEN UNIX_TIMESTAMP() - 32 * 86400 AND UNIX_TIMESTAMP() - 8 * 86400
LIMIT 500
创建的列包含unix时间戳,状态可以是-10到10之间的整数。关于创建日期的记录是均匀分布的,其中大约一半处于状态0或-10。
我有一个cron,用于选择32天到8天之间的记录,对它们进行处理,然后针对某些状态将其删除。查询如下:
{{1}}
当记录在创建间隔的开始时查询很快,但是现在清理在间隔结束时到达了记录,运行大约需要10秒钟。对该查询进行解释说,它使用索引,但是它解析了大约4000万条记录。
我的问题是我是否可以做些什么来提高查询的性能,如果可以的话,如何精确地进行查询。
谢谢。
答案 0 :(得分:1)
我认为union all
是您最好的方法:
(SELECT r.id
FROM records r
WHERE r.status = 0 AND
r.created BETWEEN UNIX_TIMESTAMP() - 32 * 86400 AND UNIX_TIMESTAMP() - 8 * 86400
LIMIT 500
) UNION ALL
(SELECT r.id
FROM records r
WHERE r.status = -10 AND
r.created BETWEEN UNIX_TIMESTAMP() - 32 * 86400 AND UNIX_TIMESTAMP() - 8 * 86400
LIMIT 500
)
LIMIT 500;
这可以使用records(status, created, id)
上的索引。
注意:如果union
可能有重复项,请使用records.id
。
您还使用了LIMIT
,而没有ORDER BY
。通常不建议这样做。
答案 1 :(得分:0)
您的索引顺序错误。您应该将IN
列(status
)首先放在(您将其列为OR
),然后将'range'列(created
)放在最后:
INDEX(status, created)
(不要给我有关“基数”的任何虚张声势;我们不在查看各个列。)
表中真的只有3列吗?您需要id
吗?如果没有,请摆脱它并更改为
PRIMARY KEY(status, created)
其他techniques用于有效地浏览大型表。