优化Postgres中的UUID查找

时间:2015-03-20 18:15:08

标签: postgresql indexing query-optimization uuid b-tree

下面的所有uuid列都使用本机Postgres uuid列类型。

有一个查找表,其中uuid(uuid类型4 - 以及可行的随机)是主键。定期从此查找表中拉出行序列,例如10,000。

然后,希望使用从查找表中检索到的那组uuid来查询其他表,通常是另外两个表,使用刚刚检索到的UUID。其他表(表A和表B)中的UUID不是主键。其他表A和B中的UUID列具有UNIQUE约束(btree索引)。

目前没有使用任何类型的JOIN进行此合并,只是简单:

  1. 查询查询表,获取uuids。
  2. 使用(1)
  3. 中的uuids查询表A.
  4. 使用(1)
  5. 中的uuids查询表B.

    问题是查询(2)和(3)的速度非常慢。因此,对于表A和表B中的大约4000行,特别是表A,通常约为30-50秒。表A有大约60M行。

    当使用EXPLAIN ANALYZE时,只处理表A,报告为在A列的uuid列上执行“索引扫描”,并在EXPLAIN ANALYZE输出中显示索引条件。

    我已经尝试了各种WHERE子句:

    • uuid = ANY('{
    • uuid = ANY(VALUES('
    • uuid ='uuid1'或uuid ='uuid2'等....

    在uuid,btree和hash索引上用btree(distinct),哈希索引表A进行实验。

    到目前为止,最快的(仍然相对较慢)是:btree并在WHERE子句中使用“ANY('{”。

    我读过的各种意见:

    • 实际上做了正确的JOIN,例如三个表格中的LEFT OUTER JOIN。
    • 使用uuid类型4是问题,它是一个随机生成的id,而不是基于序列的id。
    • 可能正在尝试work_mem。

    反正。想知道是否有其他人有任何其他建议?

    Table: "lookup"
    
    uuid: type uuid. not null. plain storage.
    datetime_stamp: type bigint. not null. plain storage.
    harvest_date_stamp: type bigint. not null. plain storage.
    state: type smallint. not null. plain storage.
    
    Indexes:
        "lookup_pkey" PRIMARY KEY, btree (uuid)
        "lookup_32ff3898" btree (datetime_stamp)
        "lookup_6c8369bc" btree (harvest_date_stamp)
        "lookup_9ed39e2e" btree (state)
    Has OIDs: no
    
    Table: "article_data"`
    
    int: type integer. not null default nextval('article_data_id_seq'::regclass). plain storage.
    title: text.
    text: text.
    insertion_date: date
    harvest_date: timestamp with time zone.
    uuid: uuid.
    
    Indexes:
        "article_data_pkey" PRIMARY KEY, btree (id)
        "article_data_uuid_key" UNIQUE CONSTRAINT, btree (uuid)
    Has OIDs: no
    

    lookup和article_data都有大约65米的行。两个问题:

    SELECT uuid FROM lookup WHERE state = 200 LIMIT 4000;
    
    OUTPUT FROM EXPLAIN (ANALYZE, BUFFERS):  
     Limit  (cost=0.00..4661.02 rows=4000 width=16) (actual time=0.009..1.036 rows=4000 loops=1)  
       Buffers: shared hit=42  
       ->  Seq Scan on lookup  (cost=0.00..1482857.00 rows=1272559 width=16) (actual time=0.008..0.777 rows=4000 loops=1)  
             Filter: (state = 200)  
             Rows Removed by Filter: 410  
             Buffers: shared hit=42  
     Total runtime: 1.196 ms  
    (7 rows)  
    

    问题:当状态为btree时,为什么这会执行序列扫描而不是索引扫描?

    SELECT article_data.id, article_data.uuid, article_data.title, article_data.text 
    FROM article_data 
    WHERE uuid = ANY ('{f0d5e665-4f21-4337-a54b-cf0b4757db65,..... 3999 more uuid's ....}'::uuid[]);
    
    OUTPUT FROM EXPLAIN (ANALYZE, BUFFERS):  
     Index Scan using article_data_uuid_key on article_data  (cost=5.56..34277.00 rows=4000 width=581) (actual time=0.063..66029.031 rows=400  
    0 loops=1)  
       Index Cond: (uuid = ANY ('{f0d5e665-4f21-4337-a54b-cf0b4757db65,5618754f-544b-4700-9d24-c364fd0ba4e9,958e37e3-6e6e-4b2a-b854-48e88ac1fdb7,  ba56b483-59b2-4ae5-ae44-910401f3221b,aa4  
    aca60-a320-4ed3-b7b4-829e6ca63592,05f1c0b9-1f9b-4e1c-8f41-07545d694e6b,7aa4dee9-be17-49df-b0ca-d6e63b0dc023,e9037826-86c4-4bbc-a9d5-6977ff7458af,db5852bf-  a447-4a1d-9673-ead2f7045589  
    ,6704d89  .......}'::uuid[]))  
       Buffers: shared hit=16060 read=4084 dirtied=292  
     Total runtime: 66041.443 ms  
    (4 rows)  
    

    问题:为什么这么慢,即使是从磁盘读取?

1 个答案:

答案 0 :(得分:0)

如果没有看到您的表格结构和explain analyze...的输出,我希望查找表上的内部联接可以提供最佳性能。 (我的table_a有大约1000万行。)

select * 
from table_a
inner join 
    -- Brain dead way to get about 1000 rows 
    -- from a renamed scratch table.
    (select test_uuid from lookup_table
     where test_id < 10000) t
on table_a.test_uuid = t.test_uuid;
"Nested Loop  (cost=0.72..8208.85 rows=972 width=36) (actual time=0.041..11.825 rows=999 loops=1)"
"  ->  Index Scan using uuid_test_2_test_id_key on lookup_table  (cost=0.29..39.30 rows=972 width=16) (actual time=0.015..0.414 rows=999 loops=1)"
"        Index Cond: (test_id   Index Scan using uuid_test_test_uuid_key on table_a  (cost=0.43..8.39 rows=1 width=20) (actual time=0.010..0.011 rows=1 loops=999)"
"        Index Cond: (test_uuid = lookup_table.test_uuid)"
"Planning time: 0.503 ms"
"Execution time: 11.953 ms"