sql - Postgresql 查询耗时超过 5 分钟

标签 sql postgresql indexing named-query postgresql-performance

我有一个包含 5 亿多行的大表。我试图找到最好的索引替代方法来稍微加快查询时间。我想根据时间戳排序会大大减慢查询时间。该表中有 15 列。

MyTable 有 @ManyToOne与 other_table 的关系。用户也可以定义最大结果。代码如下所示:

// Im showing the query itself here instead of the name of @NamedQuery inside the entity class.
TypedQuery<MyTable> query = em.createNamedQuery("SELECT m FROM my_table m WHERE m.other_table.id = :id AND m.city in :cities ORDER BY m.timestamp DESC", MyTable.class);
query.setParameter("id", id);
query.setParameter("cities", cities);
query.setMaxResults(number);
return query.getResultList();

这种类型的查询的最佳替代方法是什么?综合指数?哪种索引类型最适合这种情况?

我们有一个这样的索引,但正如我所说,这需要很长时间。
CREATE INDEX my_table_idx ON my_schema.my_table USING btree (other_table_id, timestamp DESC NULLS LAST, city)

编辑:

这是执行计划:

Limit  (cost=2876886.98..2876887.03 rows=20 width=162) (actual time=101820.279..101820.284 rows=20 loops=1)
  Buffers: shared hit=8063 read=635649 written=12198
  ->  Sort  (cost=2876886.98..2879114.34 rows=890941 width=162) (actual time=101820.277..101820.278 rows=20 loops=1)
        Sort Key: timestamp DESC
        Sort Method: top-N heapsort  Memory: 35kB
        Buffers: shared hit=8063 read=635649 written=12198
  ->  Bitmap Heap Scan on my_table  (cost=31640.64..2853179.36 rows=890941 width=162) (actual time=199.824..101221.260 rows=711774 loops=1)
        Recheck Cond: ((m_other_table_id = '14b713d5-fb1a-4dbd-c013-fat4a7f6c8e3'::uuid) AND (m_city_id = 3))
        Rows Removed by Index Recheck: 28920837
        Heap Blocks: exact=23535 lossy=615808
        Buffers: shared hit=8060 read=635649 written=12198
        ->  Bitmap Index Scan on my_table_idx  (cost=0.00..31417.90 rows=890941 width=0) (actual time=189.011..189.012 rows=711777 loops=1)
              Index Cond: ((m_other_table_id = '14b713d5-fb1a-4dbd-c013-fat4a7f6c8e3'::uuid) AND (m_city_id = 3))
              Buffers: shared hit=90 read=4276
Planning time: 0.198 ms
Execution time: 101821.109 ms

这些是我们拥有的索引。
CREATE INDEX my_table_idx ON my_schema.my_table USING btree (other_table_id, timestamp DESC NULLS LAST, city)
CREATE UNIQUE INDEX my_table_prev_id_idx ON my_schema.my_table USING btree (m_prev_id)
CREATE INDEX my_table_other_table_fk_idx ON my_schema.my_table USING btree (m_other_table_id)
CREATE UNIQUE INDEX my_table_pkey ON my_schema.my_table USING btree (m_id)
CREATE INDEX my_table_track_fk_idx ON my_schema.my_table USING btree (m_track_id)

编辑2:

我想知道为什么并行工作程序没有显示在我的执行计划中。我配置了这些设置。
max_worker_processes = 6;
max_parallel_workers = 6;
max_parallel_workers_per_gather = 3;

最佳答案

基于计划中的这一行:

Cond: ((m_other_table_id = '14b713d5-fb1a-4dbd-c013-fat4a7f6c8e3'::uuid) AND (m_city_id = 3))

你的理想指数应该在 (m_other_table_id, m_city_id) .不是 other_table_id ,不是 city .您显示的计划与查询并不真正匹配,因此很难分辨错别字在哪里 - 在显示的计划中还是在显示的查询中。

另外,由于您是通过 timestamp 订购的,我们可以将其添加到索引中。

所以,我会尝试以下索引:
CREATE INDEX idx ON my_schema.my_table USING btree 
    (m_other_table_id, m_city_id, timestamp DESC)

此处列的顺序很重要。

关于sql - Postgresql 查询耗时超过 5 分钟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60868836/

相关文章:

postgresql - 如何从 postgresql 中的查询中获取最小值、中值和最大值?

ruby-on-rails - 如何查询双belongs_to关联

python - 根据另一个 Pandas 数据框有条件地提取 Pandas 行

c - 在 C 中,使用变量初始化数组会导致堆栈溢出错误或在 R 中调用代码时导致 R 崩溃

java - 基于for循环更新数据库中的同一记录

sql - 使用 Bigquery 删除具有 "REPEATED"模式的嵌套列

c# - 在 SQL 中基于一对多表关系填充对象

java - 为什么 Hibernate 每次请求都创建新的数据库连接?

mysql - 将查询结果优化为使用文件排序;

MySQL 1062 - key '0' 的重复条目 'PRIMARY'