我现有的应用程序正在Heroku上运行,并且我使用Postgres作为数据库。
现在,由于数据量的增加,我的查询越来越慢。这是我的查询
SELECT *
FROM my_table
WHERE my_table.is_deleted = $1
AND my_table.id NOT IN (SELECT my_table_user_actions.qurb_id AS my_table_user_actions_qurb_id
FROM my_table_user_actions
WHERE my_table_user_actions.user_id = $2
AND my_table_user_actions.is_hidden = $3)
AND my_table.block_x BETWEEN $4 AND $5
AND my_table.block_y BETWEEN $6 AND $7
AND my_table.id NOT IN (SELECT sponsored_qurb_log.qurb_id AS sponsored_qurb_log_qurb_id
FROM sponsored_qurb_log
WHERE sponsored_qurb_log.qurb_id = my_table.id
AND sponsored_qurb_log.hash = $8
AND sponsored_qurb_log.user_id = $9)) AS anon_1
此查询几乎需要10秒钟才能在服务器上执行。
现在我愿意在以下列上应用索引
is_deleted
的类型为boolean
block_x
的类型为int
block_y
的类型为int
这是三列。这里is_deleted始终设置为false
,因为我一直想获取所有未删除的记录。 block_x
和block_y
是具有经度和纬度的列。
请让我知道查询的索引是什么。
这就是我在想什么
多列索引:
CREATE INDEX my_table_xandy_block ON my_table(blovk_x, block_y);
is_deleted的部分索引:
CREATE INDEX is_deleted_index ON my_table(is_deleted) WHERE is_deleted IS FALSE;
请检查我的查询,然后让我知道如何优化查询。由于我不愿意更改查询,因为我将部署新版本的代码。
答案 0 :(得分:1)
通常,您必须检查查询的EXPLAIN (ANALYZE, BUFFERS)
输出才能回答这样的问题。
但是对于您而言,这很简单:您将必须将NOT IN
子句转换为WHERE NOT EXISTS
。
一个例子:
WHERE a.x NOT IN (
SELECT b.y FROM b
)
应该成为
WHERE NOT EXISTS (
SELECT 1 FROM b
WHERE a.x = b.y
)
这样PostgreSQL可以使用“ antijoin”来处理查询,这对于较大的表将更快。
要进一步加快查询速度,请查看执行计划并适当添加索引。
如果您确实拒绝重写查询,则最好使用以下索引:
CREATE INDEX ON my_table_user_actions (user_id, is_hidden);
CREATE INDEX ON sponsored_qurb_log (qurb_id, hash, user_id);