On Mon, 07 Oct 2002 15:07:29 +0530, "Shridhar Daithankar"
<[EMAIL PROTECTED]> wrote:
>Only worry is database size. Postgresql is 111GB v/s 87 GB for mysql.

Shridhar,

here is an implementation of a set of user types: char3, char4,
char10.  Put the attached files into a new directory contrib/fixchar,
make, make install, and run fixchar.sql through psql.  Then create
your table as
        CREATE TABLE tbl (
        type            int,
        esn             char10,
        min             char10,
        datetime        timestamp,
        opc0            char3,
        ...
        rest            char4,
        field0          int,
        field1          char4,
        ...
        )

This should save 76 bytes per heap tuple and 12 bytes per index tuple,
giving a database size of ~ 76 GB.  I'd be very interested how this
affects performance.

Code has been tested for v7.2, it crashes on v7.3 beta 1.  If this is
a problem, let me know.

Servus
 Manfred
-- User type charNN: space saving replacement for char(NN)

CREATE FUNCTION charNN_in(opaque)
    RETURNS charNN
    AS '$libdir/fixchar'
    LANGUAGE 'c';

CREATE FUNCTION charNN_out(opaque)
    RETURNS opaque
    AS '$libdir/fixchar'
    LANGUAGE 'c';

CREATE TYPE charNN (
    INPUT = charNN_in,
    OUTPUT = charNN_out,
    INTERNALLENGTH = NN,
    ALIGNMENT = char
);

-- Operators
CREATE FUNCTION charNN_lt(charNN, charNN)
    RETURNS boolean
    AS '$libdir/fixchar'
    LANGUAGE 'c';

CREATE FUNCTION charNN_le(charNN, charNN)
    RETURNS boolean
    AS '$libdir/fixchar'
    LANGUAGE 'c';

CREATE FUNCTION charNN_eq(charNN, charNN)
    RETURNS boolean
    AS '$libdir/fixchar'
    LANGUAGE 'c';

CREATE FUNCTION charNN_ge(charNN, charNN)
    RETURNS boolean
    AS '$libdir/fixchar'
    LANGUAGE 'c';

CREATE FUNCTION charNN_gt(charNN, charNN)
    RETURNS boolean
    AS '$libdir/fixchar'
    LANGUAGE 'c';

CREATE FUNCTION charNN_ne(charNN, charNN)
    RETURNS boolean
    AS '$libdir/fixchar'
    LANGUAGE 'c';

CREATE OPERATOR < ( LEFTARG = charNN, RIGHTARG = charNN,
    PROCEDURE = charNN_lt,
        COMMUTATOR = >,
        NEGATOR = >=,
    RESTRICT = scalarltsel, JOIN = scalarltjoinsel
);

CREATE OPERATOR <= ( LEFTARG = charNN, RIGHTARG = charNN,
    PROCEDURE = charNN_le,
        COMMUTATOR = >=,
        NEGATOR = >,
    RESTRICT = scalarltsel, JOIN = scalarltjoinsel
);

CREATE OPERATOR = ( LEFTARG = charNN, RIGHTARG = charNN,
    PROCEDURE = charNN_eq,
        COMMUTATOR = =,
        NEGATOR = !=,
    RESTRICT = eqsel, JOIN = eqjoinsel
);

CREATE OPERATOR >= ( LEFTARG = charNN, RIGHTARG = charNN,
    PROCEDURE = charNN_ge,
        COMMUTATOR = <=,
        NEGATOR = <,
    RESTRICT = scalargtsel, JOIN = scalargtjoinsel
);

CREATE OPERATOR > ( LEFTARG = charNN, RIGHTARG = charNN,
    PROCEDURE = charNN_gt,
        COMMUTATOR = <,
        NEGATOR = <=,
    RESTRICT = scalargtsel, JOIN = scalargtjoinsel
);

CREATE OPERATOR != ( LEFTARG = charNN, RIGHTARG = charNN,
    PROCEDURE = charNN_ne,
        COMMUTATOR = !=,
        NEGATOR = =,
    RESTRICT = neqsel, JOIN = neqjoinsel
);

-- btree opclass
INSERT INTO pg_opclass (opcamid, opcname, opcintype, opcdefault, opckeytype)
    SELECT a.oid, 'charNN_ops', t.oid, true, 0
      FROM pg_am a, pg_type t
     WHERE a.amname = 'btree'
       AND t.typname = 'charNN';

--btree strategies
CREATE TEMP TABLE charNN_strat (
    strat smallint,
    opr name
);

INSERT INTO charNN_strat VALUES (1, '<');
INSERT INTO charNN_strat VALUES (2, '<=');
INSERT INTO charNN_strat VALUES (3, '=');
INSERT INTO charNN_strat VALUES (4, '>=');
INSERT INTO charNN_strat VALUES (5, '>');

SELECT o.oid AS opoid, s.strat
  INTO TEMP TABLE charNN_ops_tmp
  FROM pg_operator o, pg_type t, charNN_strat s
 WHERE t.typname = 'charNN'
   AND o.oprleft = t.oid
   AND o.oprright = t.oid
   AND o.oprname = s.opr;

INSERT INTO pg_amop (amopclaid, amopstrategy, amopreqcheck, amopopr)
    SELECT oc.oid, c.strat, false, c.opoid
      FROM pg_opclass oc, charNN_ops_tmp c, pg_am a
     WHERE opcamid = a.oid
       AND opcname = 'charNN_ops' 
       AND a.amname = 'btree';


-- support routine
CREATE FUNCTION charNN_cmp(charNN, charNN)
    RETURNS integer
    AS '$libdir/fixchar'
    LANGUAGE 'c';

INSERT INTO pg_amproc (amopclaid, amprocnum, amproc)
    SELECT oc.oid, 1, p.oid
      FROM pg_opclass oc, pg_proc p, pg_am a
     WHERE a.amname = 'btree'
       AND oc.opcamid = a.oid
       AND oc.opcname = 'charNN_ops'
       AND p.proname = 'charNN_cmp';

# fixchar Makefile
# 
# Experimental code!  Use at your own risk!
# 2002-10-08  mk

subdir = contrib/fixchar
top_builddir = ../..
include $(top_builddir)/src/Makefile.global

MODULE_big = fixchar
OBJS = char3.o char4.o char10.o
DATA_built = fixchar.sql
DOCS = README.fixchar

char%.c: fixcharNN.c.in
        sed -e 's/NN/$*/g' $< >$@

fixchar.sql: char3.sql char4.sql char10.sql
        cat $^ >$@

char%.sql: fixcharNN.sql.in
        sed -e 's/NN/$*/g' $< >$@

include $(top_srcdir)/contrib/contrib-global.mk

#include "postgres.h"

char *charNN_in(char *cstr);
char *charNN_out(char *sstr);
bool charNN_lt(char *a, char *b);
bool charNN_le(char *a, char *b);
bool charNN_eq(char *a, char *b);
bool charNN_ge(char *a, char *b);
bool charNN_gt(char *a, char *b);
bool charNN_ne(char *a, char *b);
int4 charNN_cmp(char *a, char *b);

char *
charNN_in(char *cstr)
{
        char *result;
        int len;
        int i;

        len = strlen(cstr);
        if (len > NN)
                len = NN;

        result = (char *) palloc(NN);
        for (i = 0; i < len; ++i)
                result[i] = cstr[i];

        for (; i < NN; ++i)
                result[i] = ' ';

        return result;
}/*charNN_in*/

char *
charNN_out(char *sstr)
{
        char *result;
        int i;

        if (sstr == NULL)
                return NULL;

        result = (char *) palloc(NN + 1);
        for (i = 0; i < NN; ++i)
                result[i] = sstr[i];

        result[NN] = '\0';

        return result;
}/*charNN_out*/

bool
charNN_lt(char *a, char *b)
{
        return (strncmp(a, b, NN) < 0);
}/*charNN_lt*/

bool
charNN_le(char *a, char *b)
{
        return (strncmp(a, b, NN) <= 0);
}/*charNN_le*/

bool
charNN_eq(char *a, char *b)
{
        return (strncmp(a, b, NN) == 0);
}/*charNN_eq*/

bool
charNN_ge(char *a, char *b)
{
        return (strncmp(a, b, NN) >= 0);
}/*charNN_ge*/

bool
charNN_gt(char *a, char *b)
{
        return (strncmp(a, b, NN) > 0);
}/*charNN_gt*/

bool
charNN_ne(char *a, char *b)
{
        return (strncmp(a, b, NN) != 0);
}/*charNN_ne*/

int4
charNN_cmp(char *a, char *b)
{
        return strncmp(a, b, NN);
}/*charNN_cmp*/
fixchar
=======

User data types char3, char4 and char10 as space saving replacements
for char(3), char(4), and char(10) respectively.

This is an experimental implementation for Shridhar's high volume
performance tests.  It is not expected to be usable in any real world
application.  Known problems are at least:

  . There are no casting functions
  . This does not work with multibyte character sets

Use at your own risk!


I N S T A L L
=============

. Put these files into contrib/fixchar
. cd to contrib/fixchar
. make
. make install
. cd to the directory where PG is installed
. bin/psql yourdb
yourdb=# \i share/postgresql/contrib/fixchar.sql


T E S T
=======

CREATE TABLE short (
        i INT,
        c3 char3,
        c4 char4,
        c10 char10,
        primary key (i, c3)
);
CREATE TABLE long (
        i INT,
        c3 char(3),
        c4 char(4),
        c10 char(10),
        primary key (i, c3)
);
INSERT INTO short VALUES (1, 'aaa', 'aaaa', 'a');
INSERT INTO long VALUES (1, 'aaa', 'aaaa', 'a');
INSERT INTO short SELECT i+1, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+1, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+2, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+2, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+4, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+4, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+8, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+8, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+16, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+16, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+32, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+32, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+64, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+64, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+128, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+128, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+256, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+256, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+512, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+512, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+1024, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+1024, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+2048, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+2048, c3, c4, c10 FROM long;
INSERT INTO short SELECT i+4096, c3, c4, c10 FROM short;
INSERT INTO long SELECT i+4096, c3, c4, c10 FROM long;
VACUUM VERBOSE ANALYZE short;
VACUUM VERBOSE ANALYZE long;
SELECT relname,reltuples,relpages FROM pg_class WHERE relname NOT LIKE 'pg%';
  relname   | reltuples | relpages
------------+-----------+----------
 short_pkey |      8192 |       33
 short      |      8192 |       57
 long_pkey  |      8192 |       39
 long       |      8192 |       69
(4 rows)

(2002-10-08  mk)

---------------------------(end of broadcast)---------------------------
TIP 4: Don't 'kill -9' the postmaster

Reply via email to