为什么索引没有被使用

时间:2013-11-11 20:33:27

标签: sql postgresql

我有以下表格的表格:

create table orpsnumericy2(o bigint, r bigint, p bigint, s bigint);

我在(o,r,p,s)的所有排列上建立了24个索引。

我有另一张表格如下

create table dictionaryfull (id, stringvalue);

有两个索引:(id, stringvalue)(stringvalue, id)

我使用postgres的create index命令创建了索引

然后我运行了以下命令:

explain select di1.stringvalue 
from orpsnumericy2 d1, orpsnumericy2 d2, dictionaryfull di1 
where d1.R=d2.S 
and d2.P=(select id from dictionaryFull where stringvalue='"hasSuccessor"') 
and d2.O=(select id from dictionaryFull where stringvalue='"William"') 
and d1.S=di1.id;

我从命令中获得了以下计划:

 Hash Join  (cost=8820530.24..35113870.90 rows=290 width=516)
   Hash Cond: (di1.id = d1.S)
   InitPlan 1 (returns $0)
     ->  Bitmap Heap Scan on dictionaryfull  (cost=71028.27..4406162.67 rows=1358357 width=8)
           Recheck Cond: ((stringvalue)::text = '"http://yago-knowledge.org/resource/hasSuccessor"'::text)
           ->  Bitmap Index Scan on dictionaryfull_stringvalue_id_idx  (cost=0.00..70688.68 rows=1358357 width=0)
                 Index Cond: ((stringvalue)::text = '"http://yago-knowledge.org/resource/hasSuccessor"'::text)
   InitPlan 2 (returns $1)
     ->  Bitmap Heap Scan on dictionaryfull  (cost=71028.27..4406162.67 rows=1358357 width=8)
           Recheck Cond: ((stringvalue)::text = '"http://yago-knowledge.org/resource/William_J._Murphy"'::text)
           ->  Bitmap Index Scan on dictionaryfull_stringvalue_id_idx  (cost=0.00..70688.68 rows=1358357 width=0)
                 Index Cond: ((stringvalue)::text = '"http://yago-knowledge.org/resource/William_J._Murphy"'::text)
   ->  Seq Scan on dictionaryfull di1  (cost=0.00..25274570.28 rows=271671328 width=524)
   ->  Hash  (cost=8203.39..8203.39 rows=122 width=8)
         ->  Nested Loop  (cost=0.00..8203.39 rows=122 width=8)
               ->  Index Scan using opsr1 on orpsnumericy2 d2  (cost=0.00..279.67 rows=122 width=8)
                     Index Cond: ((O = $1) AND (P = $0))
               ->  Index Scan using rops1 on orpsnumericy2 d1  (cost=0.00..64.94 rows=1 width=16)
                     Index Cond: (R = d2.S)

有人可以帮我理解为什么词典的索引没有被使用。以及为什么查询这么慢的原因。

如果有人能用简单的术语解释我的查询计划,那就太棒了

编辑:有人可以帮我找到最佳查询:

  select di1.stringvalue, di2.stringvalue, di3.stringvalue   
  from orpsnumericy2 d1, orpsnumericy2 d2, dictionaryfull di1,
       dictionaryfull di2,dictionaryfull di3 
  where d1.reification=d2.S and d2.P=(select id
        from dictionaryFull where stringvalue='"hasSuccessor"')   
  and d2.O=(select id from dictionaryFull  
      where  stringvalue='"William_J._Murphy"')  
 and d1.S=di1.id  
 and d1.P=di2.id  
 and d1.O=di3.id

1 个答案:

答案 0 :(得分:2)

select di1.stringvalue 
from orpsnumericy2 d1, orpsnumericy2 d2, dictionaryfull di1 
where d1.R=d2.S 
and d2.P=(select id from dictionaryFull where stringvalue='"hasSuccessor"') 
and d2.O=(select id from dictionaryFull where stringvalue='"William"') 
and d1.S=di1.id;

这里有三张表:

orpsnumericy2 d1 , orpsnumericy2 d2,dictionaryfull di1

您未能正确加入他们。

您需要d2.??? = di1.???的条件才是查询“慢”的原因。基本上发生的事情是您丢失了Join因此您在查询中接近cartesian product。您可能最后想要这个条件:

and d2.S=di1.id;

此外,您可能需要考虑重写类似于至少未经过测试的查询:

   select di1.stringvalue
   from dictionaryfull di1
   join orpsnumericy2 d1 on d1.S = di1.id  
   join orpsnumericy2 d2 on d2.id = d1.id
    and d2.P=(select id from dictionaryFull where stringvalue='"hasSuccessor"') 
    and d2.O=(select id from dictionaryFull where stringvalue='"William"') 

您现在的查询非常不同:

select di1.stringvalue, di2.stringvalue, di3.stringvalue   
  from orpsnumericy2 d1, orpsnumericy2 d2, dictionaryfull di1,
       dictionaryfull di2,dictionaryfull di3 
  where d1.reification=d2.S and d2.P=(select id
        from dictionaryFull where stringvalue='"hasSuccessor"')   
  and d2.O=(select id from dictionaryFull  
      where  stringvalue='"William_J._Murphy"')  
 and d1.S=di1.id  
 and d1.P=di2.id  
 and d1.O=di3.id

你现在有五个表:

orpsnumericy2 d1.orpsnumericy2 d2, dictionaryfull di1,  
dictionaryfull di2,dictionaryfull di3

你正在做的只是增加更多的复杂性并且无法进行适当的连接。我原来的解决方案仍然认为你缺少连接。因此添加更多表并没有帮助解决问题。此外,您还没有为我们提供实际查看您的架构的方案。在这个问题上,我们对这些部分的猜测都很疯狂。

您需要以下联接:

d1.x = d2.x
d1.x = d3.x
d2.x = d3.x
d1.x = di1.x
d1.x = di2.x
d1.x = di3.x
d2.x = di1.x
d2.x = di2.x
d2.x = di3.x
d3.x = di1.x
d3.x = di2.x
d3.x = di3.x
di1.x = di2.x
di1.x = di3.x
di2.x = di3.x