Re: Get more from indices.

Поиск
Список
Период
Сортировка
От Kyotaro HORIGUCHI
Тема Re: Get more from indices.
Дата
Msg-id 20140114.180810.122352231.horiguchi.kyotaro@lab.ntt.co.jp
обсуждение исходный текст
Ответ на Re: Get more from indices.  (Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp>)
Ответы Re: Get more from indices.  (Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp>)
Список pgsql-hackers
Hello, since CF4 is already closed but this patch ramains marked
as 'Ready for Committer', please let me re-post the latest
version for CF4 to get rid of vanishing :-p

> tgl> But aside from hasty typos,
> 
> Oops! I've picked up wrong node. It always denies pathkeys extension.
> 
> | !IsA(member, Var))
> 
> is a mistake of the following.
> 
> | !IsA(member->em_expr, Var))

regards,

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index 4f63906..b695e40 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -1790,6 +1790,7 @@ _outIndexOptInfo(StringInfo str, const IndexOptInfo *node)    WRITE_BOOL_FIELD(predOK);
WRITE_BOOL_FIELD(unique);   WRITE_BOOL_FIELD(immediate);
 
+    WRITE_BOOL_FIELD(allnotnull);    WRITE_BOOL_FIELD(hypothetical);    /* we don't bother with fields copied from the
pg_amentry */}
 
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 606734a..0b2f529 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -952,8 +952,11 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,    {        index_pathkeys =
build_index_pathkeys(root,index,                                              ForwardScanDirection);
 
-        useful_pathkeys = truncate_useless_pathkeys(root, rel,
-                                                    index_pathkeys);
+        if (index_pathkeys_are_extensible(root, index, index_pathkeys))
+            useful_pathkeys = root->query_pathkeys;
+        else
+            useful_pathkeys = truncate_useless_pathkeys(root, rel,
+                                                        index_pathkeys);        orderbyclauses = NIL;
orderbyclausecols= NIL;    }
 
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 9c8ede6..ad3a8b7 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -502,6 +502,60 @@ build_index_pathkeys(PlannerInfo *root,}/*
+ * index_pathkeys_are_extensible
+ *      Check whether the pathkeys are extensible to query_pathkeys.
+ */
+bool
+index_pathkeys_are_extensible(PlannerInfo *root,
+                              IndexOptInfo *index,
+                              List *pathkeys)
+{
+    bool        result;
+    ListCell   *lc1;
+
+    if (root->query_pathkeys == NIL || pathkeys == NIL)
+        return false;
+
+    if (!index->unique || !index->immediate || !index->allnotnull)
+        return false;
+
+    if (!pathkeys_contained_in(pathkeys, root->query_pathkeys))
+        return false;
+
+    if (list_length(pathkeys) == list_length(root->query_pathkeys))
+        return true;
+
+    result = true;
+    foreach(lc1, root->query_pathkeys)
+    {
+        PathKey    *pathkey = (PathKey *) lfirst(lc1);
+        bool        found = false;
+        ListCell   *lc2;
+
+        foreach(lc2, pathkey->pk_eclass->ec_members)
+        {
+            EquivalenceMember *member = (EquivalenceMember *) lfirst(lc2);
+
+            if (!bms_equal(member->em_relids, index->rel->relids) ||
+                !IsA(member->em_expr, Var))
+                continue;
+            else
+            {
+                found = true;
+                break;
+            }
+        }
+
+        if (!found)
+        {
+            result = false;
+            break;
+        }
+    }
+    return result;
+}
+
+/* * build_expression_pathkey *      Build a pathkeys list that describes an ordering by a single expression *
usingthe given sort operator.
 
diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c
index de981cb..4e24220 100644
--- a/src/backend/optimizer/util/plancat.c
+++ b/src/backend/optimizer/util/plancat.c
@@ -333,6 +333,26 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
info->immediate= index->indimmediate;            info->hypothetical = false;
 
+            info->allnotnull = true;
+            for (i = 0; i < ncolumns; i++)
+            {
+                int            attrno = info->indexkeys[i];
+
+                if (attrno == 0)
+                {
+                    info->allnotnull = false;
+                    break;
+                }
+                else if (attrno > 0)
+                {
+                    if (!relation->rd_att->attrs[attrno - 1]->attnotnull)
+                    {
+                        info->allnotnull = false;
+                        break;
+                    }
+                }
+            }
+            /*             * Estimate the index size.  If it's not a partial index, we lock             * the
number-of-tuplesestimate to equal the parent table; if it
 
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index a9219e0..d9a3b9b 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -525,6 +525,7 @@ typedef struct IndexOptInfo    bool        predOK;            /* true if predicate matches query */
  bool        unique;            /* true if a unique index */    bool        immediate;        /* is uniqueness
enforcedimmediately? */
 
+    bool        allnotnull;        /* true if index's keys are all not null */    bool        hypothetical;    /* true
ifindex doesn't really exist */    bool        canreturn;        /* can index return IndexTuples? */    bool
amcanorderbyop;/* does AM support order by operator result? */
 
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 999adaa..5ee2e56 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -196,5 +196,8 @@ extern List *truncate_useless_pathkeys(PlannerInfo *root,                          RelOptInfo *rel,
                        List *pathkeys);extern bool has_useful_pathkeys(PlannerInfo *root, RelOptInfo *rel);
 
+extern bool index_pathkeys_are_extensible(PlannerInfo *root,
+                                          IndexOptInfo *index,
+                                          List *pathkeys);#endif   /* PATHS_H */
diff --git a/src/test/isolation/expected/drop-index-concurrently-1.out
b/src/test/isolation/expected/drop-index-concurrently-1.out
index 75dff56..ab96fa0 100644
--- a/src/test/isolation/expected/drop-index-concurrently-1.out
+++ b/src/test/isolation/expected/drop-index-concurrently-1.out
@@ -19,10 +19,8 @@ Sortstep explains: EXPLAIN (COSTS OFF) EXECUTE getrow_seq;QUERY PLAN     
-Sort           
-  Sort Key: id, data
-  ->  Seq Scan on test_dc
-        Filter: ((data)::text = '34'::text)
+Index Scan using test_dc_pkey on test_dc
+  Filter: ((data)::text = '34'::text)step select2: SELECT * FROM test_dc WHERE data=34 ORDER BY id,data;id
data           

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Kyotaro HORIGUCHI
Дата:
Сообщение: Re: UNION ALL on partitioned tables won't use indices.
Следующее
От: Kyotaro HORIGUCHI
Дата:
Сообщение: Re: Using indices for UNION.