Vertical Partitioning with TOAST - Mailing list pgsql-hackers

From Junji TERAMOTO
Subject Vertical Partitioning with TOAST
Date
Msg-id 438EBB5C.9070304@lab.ntt.co.jp
Whole thread Raw
Responses Re: Vertical Partitioning with TOAST
List pgsql-hackers
Hi all,

I wrote a experimental patch for a vertical partitioning
function.

I decided to use the code of TOAST to create the function
easily. In a word, the row that the user specified is forcedly
driven out with TOAST.

The performance gain of 10% was seen by driving out c_data of the
customer table in the DBT-2 benchmark in our environment.

The mechanism of TOAST is an overdesigned system to use it for a
vertical partitioning. Because the overhead of processing is large,
the performance might down according to the environment.

There are seriously a lot of things that should be considered if
a vertical partitioning is mounted.
For instance, TOAST index is omitted, and ctid is used for link.

Your comments are welcome. Thanks.

---
How To Use
---
Use "ALTER TABLE" command.
http://www.postgresql.org/docs/8.1/static/sql-altertable.html

 ALTER TABLE name ALTER COLUMN column SET STRAGE FORCEEXTERNAL;

I do not understand whether "FORCEEXTERNAL" is an appropriate
word. Please teach when there is a better word...


--
Junji Teramoto
diff -purN postgresql-8.1.0.org/src/backend/access/heap/heapam.c postgresql-8.1.0/src/backend/access/heap/heapam.c
--- postgresql-8.1.0.org/src/backend/access/heap/heapam.c    2005-10-15 11:49:08.000000000 +0900
+++ postgresql-8.1.0/src/backend/access/heap/heapam.c    2005-12-01 15:31:38.307713257 +0900
@@ -1070,6 +1070,36 @@ heap_get_latest_tid(Relation relation,
     }                            /* end of loop */
 }

+// Add by junji from here
+/*
+ *    has_rel_forceexternal - Is there "SET STORAGE FORCEEXTERNAL"ed rows?
+ */
+bool
+has_rel_forceexternal(Relation relation)
+{
+    TupleDesc    tupleDesc;
+    Form_pg_attribute *att;
+    int            numAttrs;
+    int            i;
+
+    /*
+     * Get the tuple descriptor and break down the tuple(s) into fields.
+     */
+    tupleDesc = relation->rd_att;
+    att = tupleDesc->attrs;
+    numAttrs = tupleDesc->natts;
+
+    for (i = 0; i < numAttrs; i++)
+    {
+        if (att[i]->attstorage == 'f')
+            return true;
+    }
+
+    return false;
+}
+// Add by junji to here
+
+
 /*
  *    heap_insert        - insert tuple into a heap
  *
@@ -1130,6 +1160,9 @@ heap_insert(Relation relation, HeapTuple
      * out-of-line attributes from some other relation, invoke the toaster.
      */
     if (HeapTupleHasExternal(tup) ||
+// Add by junji from here
+        (has_rel_forceexternal(relation)) ||
+// Add by junji to here
         (MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD))
         heap_tuple_toast_attrs(relation, tup, NULL);

@@ -1762,6 +1795,9 @@ l2:
      */
     need_toast = (HeapTupleHasExternal(&oldtup) ||
                   HeapTupleHasExternal(newtup) ||
+// Add by junji from here
+                  (has_rel_forceexternal(relation)) ||
+// Add by junji to here
                   (MAXALIGN(newtup->t_len) > TOAST_TUPLE_THRESHOLD));

     newtupsize = MAXALIGN(newtup->t_len);
diff -purN postgresql-8.1.0.org/src/backend/access/heap/tuptoaster.c
postgresql-8.1.0/src/backend/access/heap/tuptoaster.c
--- postgresql-8.1.0.org/src/backend/access/heap/tuptoaster.c    2005-10-15 11:49:09.000000000 +0900
+++ postgresql-8.1.0/src/backend/access/heap/tuptoaster.c    2005-12-01 15:29:29.722579466 +0900
@@ -512,6 +512,46 @@ toast_insert_or_update(Relation rel, Hea
         }
     }

+// Add by junji from here
+    /*
+     * We look for attributes of attstorage 'f'.
+     */
+    if (rel->rd_rel->reltoastrelid != InvalidOid)
+    {
+        Datum        old_value;
+
+        /*------
+         * Search for the biggest yet inlined attribute with
+         * attstorage equals 'x' or 'e'
+         *------
+         */
+        for (i = 0; i < numAttrs; i++)
+        {
+            if (toast_action[i] == 'p')
+                continue;
+            if (VARATT_IS_EXTERNAL(toast_values[i]))
+                continue;
+            if (att[i]->attstorage != 'f')
+                continue;
+
+            /*
+             * Store this external
+             */
+            old_value = toast_values[i];
+            toast_action[i] = 'p';
+            toast_values[i] = toast_save_datum(rel, toast_values[i]);
+            if (toast_free[i])
+                pfree(DatumGetPointer(old_value));
+
+            toast_free[i] = true;
+            toast_sizes[i] = VARATT_SIZE(toast_values[i]);
+
+            need_change = true;
+            need_free = true;
+        }
+    }
+// Add by junji to here
+
     /* ----------
      * Compress and/or save external until data fits into target length
      *
diff -purN postgresql-8.1.0.org/src/backend/commands/tablecmds.c postgresql-8.1.0/src/backend/commands/tablecmds.c
--- postgresql-8.1.0.org/src/backend/commands/tablecmds.c    2005-10-15 11:49:15.000000000 +0900
+++ postgresql-8.1.0/src/backend/commands/tablecmds.c    2005-12-01 15:29:29.726577573 +0900
@@ -3439,6 +3439,10 @@ ATExecSetStorage(Relation rel, const cha
         newstorage = 'x';
     else if (pg_strcasecmp(storagemode, "main") == 0)
         newstorage = 'm';
+// Add by junji from here
+    else if (pg_strcasecmp(storagemode, "forceexternal") == 0)
+        newstorage = 'f';
+// Add by junji to here
     else
     {
         ereport(ERROR,
@@ -6045,8 +6049,14 @@ needs_toast_table(Relation rel)
     tupdesc = rel->rd_att;
     att = tupdesc->attrs;

+
+
     for (i = 0; i < tupdesc->natts; i++)
     {
+// Add by junji from here
+        if (att[i]->attstorage == 'f')
+            return true;
+// Add by junji to here
         if (att[i]->attisdropped)
             continue;
         data_length = att_align(data_length, att[i]->attalign);
diff -purN postgresql-8.1.0.org/src/include/access/heapam.h postgresql-8.1.0/src/include/access/heapam.h
--- postgresql-8.1.0.org/src/include/access/heapam.h    2005-10-15 11:49:42.000000000 +0900
+++ postgresql-8.1.0/src/include/access/heapam.h    2005-12-01 15:29:29.726577573 +0900
@@ -155,6 +155,10 @@ extern void heap_get_latest_tid(Relation
                     ItemPointer tid);
 extern void setLastTid(const ItemPointer tid);

+// Add by junji from here
+extern bool has_rel_forceexternal(Relation relation);
+// Add by junji to here
+
 extern Oid heap_insert(Relation relation, HeapTuple tup, CommandId cid,
             bool use_wal, bool use_fsm);
 extern HTSU_Result heap_delete(Relation relation, ItemPointer tid,

pgsql-hackers by date:

Previous
From: Alvaro Herrera
Date:
Subject: Re: Another way to reduce pg_subtrans lookup overhead
Next
From: Peter Eisentraut
Date:
Subject: Re: [pgsql-www] Upcoming PG re-releases