我尝试在包含数千万行的表中的外键列上添加索引,并且我运行的半复杂查询从4秒到10毫秒执行时间。太好了!
然后我再次尝试删除它以进行更多测试,但是当我执行相同的查询时,它仍然需要10毫秒(与添加索引之前的4秒相比)。
删除索引会重置性能提升吗?如果没有,我怎样才能完全删除索引?
查询看起来像这样(此查询每分钟运行一次并将结果存储在另一个表中):
SELECT COUNT(*) AS count
FROM (
SELECT MAX(ze.timestamp) AS time, r.device_id
FROM loc_zone_events ze
INNER JOIN loc_zones z ON ze.zone_id = z.id
INNER JOIN raw_events r ON ze.raw_event_id = r.id
WHERE z.app_id = 1
AND ROUND(EXTRACT('epoch' FROM NOW() - ze.timestamp) / 60) BETWEEN 0 AND 10
GROUP BY r.device_id
ORDER BY time DESC
) AS t
答案 0 :(得分:4)
DROP INDEX
完全删除索引。
事务必须在新查询生效之前提交,但这通常不是问题。您可能正在看到其他测试工件,如:
首先,删除完全不必要的部分:
SELECT COUNT(*) AS count
FROM (
SELECT 1
FROM loc_zones z
JOIN loc_zone_events ze ON ze.zone_id = z.id
JOIN raw_events r ON r.id = ze.raw_event_id
WHERE z.app_id = 1
AND round(EXTRACT('epoch' FROM NOW() - ze.timestamp) / 60) BETWEEN 0 AND 10
GROUP BY r.device_id
) AS t;
或者:
SELECT COUNT(DISTINCT r.device_id) AS count
FROM loc_zones z
JOIN loc_zone_events ze ON ze.zone_id = z.id
JOIN raw_events r ON r.id = ze.raw_event_id
WHERE z.app_id = 1
AND round(EXTRACT('epoch' FROM NOW() - ze.timestamp) / 60) BETWEEN 0 AND 10
(不一定更快,count(DISTINCT col)
不是表演英雄。)
但还有更多:
WHERE
条件round(...)
不是sargable。要检索“最近10分钟”的事件,请改为使用:
...
AND ze.timestamp >= now() - interval '10 min'
AND ze.timestamp < now(); -- only if there can be timestamps in the future
这是可以使用的,可以使用ze.timestamp
上的索引。
注意: 您的表达式使用round()
代替trunc()
,这有效
覆盖范围(-0.5, 10.5)
,如果没有未来的时间戳,则为11分钟(不是10分钟)或 10.5分钟。以某种方式处理这种差异......
由于只有最后10分钟似乎相关,您可以使用部分索引进一步改进。这里的特殊困难是移动时间范围。这个相关的答案有一个完整的解决方案:
在此基础上,您将获得一个部分索引,如:
CREATE INDEX ze_timestamp_recent_idx ON tbl (timestamp DESC);
WHERE created_at > f_min_ts();
并调整查询,如:
WHERE ...
AND ze.timestamp > f_min_ts() -- to match partial index
AND ze.timestamp >= now() - interval '10 min'
AND ze.timestamp < now();
除此之外:不要使用基本类型名称timestamp
作为列名。
答案 1 :(得分:0)
这取决于您使用的数据库。
1。)如果您有一个大型数据库(如您所述)..很可能您会对其进行分区。并在分区上创建索引。
2。)如果您在运行查询时在大型表上创建索引,该查询也会减慢它的速度。 b / c现在你的两个进程正在使用数据库资源。
3。)当你运行查询时,是否还有其他进程插入/更新/删除行?你有足够的临时空间吗?你的查询是在进行排序/分组操作吗?
这些都很重要,而且更重要的是数据库的架构......在我看来。
喝彩!