我有以下查询:
devapp=> Explain SELECT DISTINCT "chaindata_tokentransfer"."emitting_contract" FROM "chaindata_tokentransfer" WHERE (("chaindata_tokentransfer"."to_addr" = 100 OR "chaindata_tokentransfer"."from_addr" = 100) AND "chaindata_tokentransfer"."chain_id" = 1 AND "chaindata_tokentransfer"."block_number" >= 10000);
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Unique (cost=29062023.48..29062321.43 rows=8870 width=4)
-> Sort (cost=29062023.48..29062172.45 rows=59591 width=4)
Sort Key: emitting_contract
-> Bitmap Heap Scan on chaindata_tokentransfer (cost=28822428.06..29057297.07 rows=59591 width=4)
Recheck Cond: (((to_addr = 100) OR (from_addr = 100)) AND (chain_id = 1) AND (block_number >= 10000))
-> BitmapAnd (cost=28822428.06..28822428.06 rows=59591 width=0)
-> BitmapOr (cost=4209.94..4209.94 rows=351330 width=0)
-> Bitmap Index Scan on chaindata_tokentransfer_to_addr_284dc4bc (cost=0.00..1800.73 rows=150953 width=0)
Index Cond: (to_addr = 100)
-> Bitmap Index Scan on chaindata_tokentransfer_from_addr_ef8ecd8c (cost=0.00..2379.41 rows=200377 width=0)
Index Cond: (from_addr = 100)
-> Bitmap Index Scan on chaindata_tokentransfer_chain_id_block_number_tx_eeeac2a4_idx (cost=0.00..28818202.98 rows=1315431027 width=0)
Index Cond: ((chain_id = 1) AND (block_number >= 10000))
(13 rows)如您所见,在chaindata_tokentransfer_chain_id_block_number_tx_eeeac2a4_idx上进行最后一次索引扫描的成本非常高。查询正在超时。如果从查询中删除chain_id和block_number上的筛选器,则查询将在合理的时间内执行。由于这个新的约束较少的查询工作正常,如果索引不存在,而且它只是一个额外的过滤器,我希望即使是原始的更受约束的查询也能工作。如何在不删除索引的情况下实现这一点?
发布于 2022-05-24 02:23:03
您可能可以通过对索引列执行一些虚拟算法来禁用索引。
...AND "chaindata_tokentransfer"."chain_id" + 0 = 1...如果您将其投入到生产中,请确保添加一个代码注释,说明您为什么要做这么奇怪的事情。
我很好奇它为什么选择使用这个指数,尽管它显然知道它有多么可怕。如果您显示了禁用索引的查询计划,也许我们可以找出这一点。
如果虚拟算法不起作用,您可以做的是启动一个事务,删除索引,执行查询(或者只是对它的解释),然后回滚删除。这可能不是您在生产中经常要做的事情(特别是因为当索引被删除直到回滚时,表将被锁定。也是因为你可能不小心犯了!)但是得到这个计划可能是值得的。
https://stackoverflow.com/questions/72354714
复制相似问题