sql - 慢速选择 - PostgreSQL

标签 sql postgresql

我有以下选择,在大型数据库上速度很慢:

SELECT eventid 
FROM track_event 
WHERE inboundid IN (SELECT messageid FROM temp_message);

temp_message 表很小(100 行),只有一列(messageid varchar),列上有一个 btree 索引。

track_event 表有 19 列和近 1300 万行。此查询中使用的列(eventid bigint 和 inboundid varchar)都有 btree 索引。

我无法从大数据库复制/粘贴解释计划,但这是来自具有相同模式的较小数据库(track_event 中只有 348 行)的计划:

 explain analyse SELECT eventid FROM track_event WHERE inboundid IN (SELECT messageid FROM temp_message);
                                                           QUERY PLAN                                                               
----------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop Semi Join  (cost=0.00..60.78 rows=348 width=8) (actual time=0.033..3.186 rows=348 loops=1)
->  Seq Scan on track_event  (cost=0.00..8.48 rows=348 width=25) (actual time=0.012..0.860 rows=348 loops=1)
->  Index Scan using temp_message_idx on temp_message  (cost=0.00..0.48 rows=7 width=32) (actual time=0.005..0.005 rows=1 loops=348)
      Index Cond: ((temp_message.messageid)::text = (track_event.inboundid)::text)
Total runtime: 3.349 ms
(5 rows)

在大型数据库上,这个查询大约需要 450 秒。谁能看到任何明显的加速?我注意到在解释计划中的 track_event 上有一个 Seq Scan - 我想我想失去它,但无法确定我可以使用哪个索引。

编辑

Postgres 9.0

track_event 表是一个非常大的复杂模式的一部分,我无法对其进行重大更改。这是信息,包括我刚刚添加的新索引:

            Table "public.track_event"
       Column       |           Type           | Modifiers 
--------------------+--------------------------+-----------
 eventid            | bigint                   | not null
 messageid          | character varying        | not null
 inboundid          | character varying        | not null
 newid              | character varying        | 
 parenteventid      | bigint                   | 
 pmmuser            | bigint                   | 
 eventdate          | timestamp with time zone | not null
 routeid            | integer                  | 
 eventtypeid        | integer                  | not null
 adminid            | integer                  | 
 hostid             | integer                  | 
 reason             | character varying        | 
 expiry             | integer                  | 
 encryptionendpoint | character varying        | 
 encryptionerror    | character varying        | 
 encryptiontype     | character varying        | 
 tlsused            | integer                  | 
 tlsrequested       | integer                  | 
 encryptionportal   | integer                  | 
Indexes:
    "track_event_pk" PRIMARY KEY, btree (eventid)
    "foo" btree (inboundid, eventid)
    "px_event_inboundid" btree (inboundid)
    "track_event_idx" btree (messageid, eventtypeid)
Foreign-key constraints:
    "track_event_parent_fk" FOREIGN KEY (parenteventid) REFERENCES track_event(eventid)
    "track_event_pmi_route_fk" FOREIGN KEY (routeid) REFERENCES pmi_route(routeid)
    "track_event_pmim_smtpaddress_fk" FOREIGN KEY (pmmuser) REFERENCES pmim_smtpaddress(smtpaddressid)
    "track_event_track_adminuser_fk" FOREIGN KEY (adminid) REFERENCES track_adminuser(adminid)
    "track_event_track_encryptionportal_fk" FOREIGN KEY (encryptionportal) REFERENCES track_encryptionportal(id)
    "track_event_track_eventtype_fk" FOREIGN KEY (eventtypeid) REFERENCES track_eventtype(eventtypeid)
    "track_event_track_host_fk" FOREIGN KEY (hostid) REFERENCES track_host(hostid)
    "track_event_track_message_fk" FOREIGN KEY (inboundid) REFERENCES track_message(messageid)
Referenced by:
    TABLE "track_event" CONSTRAINT "track_event_parent_fk" FOREIGN KEY (parenteventid) REFERENCES track_event(eventid)
    TABLE "track_eventaddress" CONSTRAINT "track_eventaddress_track_event_fk" FOREIGN KEY (eventid) REFERENCES track_event(eventid)
    TABLE "track_eventattachment" CONSTRAINT "track_eventattachment_track_event_fk" FOREIGN KEY (eventid) REFERENCES track_event(eventid)
    TABLE "track_eventrule" CONSTRAINT "track_eventrule_track_event_fk" FOREIGN KEY (eventid) REFERENCES track_event(eventid)
    TABLE "track_eventthreatdescription" CONSTRAINT "track_eventthreatdescription_track_event_fk" FOREIGN KEY (eventid) REFERENCES track_event(eventid)
    TABLE "track_eventthreattype" CONSTRAINT "track_eventthreattype_track_event_fk" FOREIGN KEY (eventid) REFERENCES track_event(eventid)
    TABLE "track_quarantineevent" CONSTRAINT "track_quarantineevent_track_event_fk" FOREIGN KEY (eventid) REFERENCES track_event(eventid)

最佳答案

您的查询正在对较大的表进行全表扫描。一个明显的加速是在 event_track(inboundid, eventid) 上添加索引。 Postgres 应该能够在您的查询中使用所写的索引。您可以将查询重写为:

SELECT te.eventid
FROM track_event te join
     temp_message tm
     on te.inboundid  = tm.messageid;

绝对应该使用索引。 (如果 temp_message 表中有重复项,您可能需要 select distinct te.eventid。)

编辑:

最后一次尝试重写是反转查询:

select (select eventid from track_event te WHERE tm.messageid = te.inboundid) as eventid
from temp_message tm;

这应该强制使用索引。如果存在不匹配项,您可能需要:

select eventid
from (select (select eventid from track_event te WHERE tm.messageid = te.inboundid) as eventid
      from temp_message tm
     ) tm
where eventid is not null;

关于sql - 慢速选择 - PostgreSQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18508866/

相关文章:

postgresql - Postgres 数据库大小和表大小总和不匹配

sql - 如何在 PostgreSQL 中有条件地查找模式

r - 如何在 Heroku 上安装 libpq?

c# - 将数据表中的多行连接到数组中

sql - 如何按从初始日期开始的日期范围进行分组

c++ - inNull(sqlite3_stmt *, int col) 是否有一个 bool 允许我检查它?

sql - 甲骨文中右对齐左零填充?

行之间的Postgresql差异

postgresql - 在面板数据上按组、时间和日期创建条件变量

SQL BETWEEN 不工作