SlideShare a Scribd company logo
1 of 107
Download to read offline
1
Friday, March 25, 2011
Your Database!!
                                Denish Patel
                               Database Architect
                         OmniTi Computer Consulting Inc.
                                denish@omniti.com


                                        1
Friday, March 25, 2011
2
Friday, March 25, 2011
Who am I ?
                     •   Denish Patel
                         •   Database Architect
                         •   4+ Years with OmniTi
                     •   Expertise
                         •   Heterogeneous Databases
                             •   PostgreSQL, Oracle, MySQL
                         •   Very Large databases
                         •   Performance tuning
                             •   Application level
                             •   SQL tuning
                             •   Database and OS parameters
                             •   Objects tuning      2
Friday, March 25, 2011
Who am I ?
                     •   Denish Patel
                         •   Database Architect
                         •   4+ Years with OmniTi
                     •   Expertise
                         •   Heterogeneous Databases
                             •   PostgreSQL, Oracle, MySQL
                         •   Very Large databases
                         •   Performance tuning
                             •   Application level       OmniTi is hiring!
                             •   SQL tuning
                             •   Database and OS parameters
                             •   Objects tuning      2
Friday, March 25, 2011
3
Friday, March 25, 2011
Agenda
                     •Why bloat ?
                     •Issues
                     •Identify bloat
                      •Tables
                      •Indexes
                     •Bloat removal toolkit
                     •Monitoring and trending
                                      3
Friday, March 25, 2011
4
Friday, March 25, 2011
why bloat?

                     •MVCC
                     •ACID
                     •Updates & Deletes


                                      4
Friday, March 25, 2011
5
Friday, March 25, 2011
MVCC method-1




                         5
Friday, March 25, 2011
MVCC method-1




                         5
Friday, March 25, 2011
MVCC method-1
                     !


                                                          34..-+56''
                                            '   !:723,'
                                                          7$89$"&'
                                  !"#$%&'
                         ,+-.$'
                         /+&+'              (0/1,2'

                                  ()*+&$                     ><??!,'
                                                '
                                            /2;2,2'


                                            72;2>,''
                                                               ,31:7'
                                                               ;<='
                                                     5
Friday, March 25, 2011
6
Friday, March 25, 2011
MVCC method-2




                         6
Friday, March 25, 2011
MVCC method-2




                         6
Friday, March 25, 2011
MVCC method-2
                    !
                                               &   3./,-!&
                                     !"#$%&
                         /,0,4!&&    '"("&

                                               )*'+!,&



                                    !-+./&     ',0,!,&
                                    012&

                                              41553!&

                                        6
Friday, March 25, 2011
7
Friday, March 25, 2011
Issues
                     •Unnecessary costly I/O operations
                     •Poor database tables access time
                     •Increase maintenance time
                     •Waste of resources
                      •RAM
                      •CPU
                      •Disk
                                       7
Friday, March 25, 2011
8
Friday, March 25, 2011
Prevent Bloat
                     • autovacuum =on
                     • vacuum manually between batch updates
                     • Truncate table
                     • Free Space Map
                      • <= PostgreSQL 8.3
                         • max_fsm_pages
                         • max_fsm_tables
                      • >=PostgreSQL 8.4
                         • auto sizing free space map
                                           8
Friday, March 25, 2011
9
Friday, March 25, 2011
BEWARE!
                     • Bug: long running auto-vacuum workers
                     • PostgreSQL Version Affected
                        • 8.3.10
                        • 8.3.11
                        • 8.3.12
                        • 8.4.4
                        • 8.4.5
                                       9
Friday, March 25, 2011
BEWARE!
                     • Bug: long running auto-vacuum workers
                     • PostgreSQL Version Affected
                        • 8.3.10
                        • 8.3.11
                        • 8.3.12
                        • 8.4.4
                        • 8.4.5
                            Upgrade to latest release !!
                                         9
Friday, March 25, 2011
10
Friday, March 25, 2011
Measure Bloat

                     •Bloat Report
                      •pg_bloat_report (OmniTI Labs)
                     •Nagios Monitoring
                      •Check_postgres_bloat

                                     10
Friday, March 25, 2011
11
Friday, March 25, 2011
pg_bloat_report
                           Bloat Report Tables

          1. omniti.hits  1969348 of 4255960 pages wasted (46.3%),
                              15 GB of 32 GB.
         2. omniti.clients 279979 of 370509 pages wasted (75.6%),
                            2187 MB of 2895 MB.

                           Bloat Report Indexes

       1. omniti.hits_pk     51275 of 71075 pages wasted (72.1%),
                            401 MB of 555 MB.
        2. omniti.clients_tz 47550 of 71271 pages wasted (66.7%),
                            371 MB 11 557 MB.
                                    of
Friday, March 25, 2011
12
Friday, March 25, 2011
check_postgres_bloat


                               Notification Type: PROBLEM
                                        Host: omniti
                                      State: CRITICAL
                          Date/Time: Wed Feb 16 11:24:56 UTC 2011
                           Additional Info: POSTGRES_BLOAT
                           CRITICAL: DB "omniti" (host:omniti)
                         (port=5432) table omniti.hits rows:23995164
                           pages:2858893 shouldbe:2278176 (1.3X)
                               wasted size:4757233664 (4 GB)

                                            12
Friday, March 25, 2011
13
Friday, March 25, 2011
bloat removal
                             toolkit
                     • Offline - with locking
                      • Vacuum
                      • Vacuum Full
                      • Cluster
                      • Cluster vs Vacuum Full
                     • Online - with minimal locking
                      • compact_table
                      • pg_reorg
                                          13
Friday, March 25, 2011
14
Friday, March 25, 2011
14
Friday, March 25, 2011
15
Friday, March 25, 2011
vacuum
                     • Auto vacuum
                     • VACUUM [verbose|analyze] table
                      • Reclaims storage occupied by dead
                           tuples

                         • Reclaimed space available to re-use
                         • Normally free space doesn’t return to
                           OS

                         • No exclusive table lock
                                           15
Friday, March 25, 2011
16
Friday, March 25, 2011
vacuum full
                     • VACUUM FULL table
                      • Compact table based on dead rows
                        • Starting PostgreSQL 9.0 , it’s rewrite
                             entire table and indexes (like CLUSTER)

                         • Reclaimed space available to re-use
                         • Space returned to OS
                         • Table Exclusive lock
                         • Expensive operation
                                            16
Friday, March 25, 2011
17
Friday, March 25, 2011
17
Friday, March 25, 2011
18
Friday, March 25, 2011
cluster
                         •CLUSTER [verbose] table_name
                          [USING index_name]

                          •Create reorganized copy of table
                            based on index

                          •Rebuild indexes too
                          •Requires Exclusive Lock on table
                          •Expensive Operation
                                         18
Friday, March 25, 2011
19
Friday, March 25, 2011
cluster vs vacuum full

                                             It’s just rewrite of table without
                 Order based on Index
                                                      any specific order

                         Table needs index         Doesn’t need index

                                             Bloat indexes (Pre PostgreSQL
                    Doesn’t bloat index
                                                          9.0)
                                             Overall Operation Slower (Pre
              Overall operation Faster
                                                    PostgreSQL 9.0)

                          Recommended              Not recommended
                                             19
Friday, March 25, 2011
20
Friday, March 25, 2011
20
Friday, March 25, 2011
21
Friday, March 25, 2011
compact_table
                     •Developed by OmniTi
                     •Reorganize rows to empty pages at the
                         end based on ctid

                     •ctid - (page number, tuple number)
                     •When we update a row, the row's ctid
                         changes, because the update creates a
                         new version of the row and leaves the
                         old version behind
                                         21
Friday, March 25, 2011
22
Friday, March 25, 2011
compact_table
                                                postgres=# select ctid,* from bar;
                                                           ctid | a | b
                                                         -------+---+---
                                                           (0,1) | 1 | 1
                                                           (0,2) | 2 | 1
                                                            (2 rows)

                                           postgres=# update bar set a=3 where a=2;
                                                          UPDATE 1
                                               postgres=# select ctid,* from bar;
                                                          ctid | a | b
                                                        -------+---+---
                                                          (0,1) | 1 | 1
                                                          (0,3) | 3 | 1
                                                           (2 rows)

                                                postgres=# vacuum verbose bar;
                                                                .
                                                                .
                         INFO: "bar": found 1 removable, 2 nonremovable row versions in 1 out of 1 pages
                                       DETAIL: 0 dead row versions cannot be removed yet.
                                                            VACUUM
                                                             22
Friday, March 25, 2011
23
Friday, March 25, 2011
compact_table




                          23
Friday, March 25, 2011
compact_table
                                postgres=# truncate table bar;
                                     TRUNCATE TABLE
                  postgres=# insert into bar select generate_series(1,1000);
                                       INSERT 0 1000
                         postgres=# delete from bar where a %2 = 0;
                                        DELETE 500
                            postgres=# select max(ctid) from bar;
                                               max
                                            --------
                                             (4,95)
                                           (1 row)
                               postgres=# vacuum verbose bar;
                        INFO: "bar": found 0 removable, 500
                  nonremovable row versions in 5 out of 5 pages
                                          VACUUM
                                             23
Friday, March 25, 2011
24
Friday, March 25, 2011
compact_table
                                        postgres=# begin;
                                              BEGIN
                         postgres=# update bar set a=a where ctid>='(3,0)';
                                          UPDATE 161
                         postgres=# update bar set a=a where ctid>='(3,0)';
                                          UPDATE 161
                         postgres=# update bar set a=a where ctid>='(3,0)';
                                           UPDATE 48
                         postgres=# update bar set a=a where ctid>='(3,0)';
                                           UPDATE 48
                         postgres=# update bar set a=a where ctid>='(3,0)';
                                           UPDATE 34
                         postgres=# update bar set a=a where ctid>='(3,0)';
                                           UPDATE 0
                                       postgres=# commit;
                                            COMMIT
                                 postgres=# vacuum verbose bar;
                                                 .
                                                 .
                                INFO: "bar": truncated 5 to 3 pages
                                                 .
                                            VACUUM
                                              24
Friday, March 25, 2011
25
Friday, March 25, 2011
compact_table
                     •Pretty safe update process
                     •No additional changes required
                     •Slow process
                     •Generate Index bloat
                     •Under development
                     •Not tested in production
                     •Future consideration?
                                      25
Friday, March 25, 2011
26
Friday, March 25, 2011
26
Friday, March 25, 2011
27
Friday, March 25, 2011
pg_reorg
                     • Developed by NTT OSS Center
                     • Reorganize table with very short lock
                      • Needs Primary Key
                      • Not Null Unique Key works!
                     • CLUSTER online
                      • ORDER BY Key
                     • VACUUM FULL Online
                      • Rewrite without ORDER BY
                     • Build and Install like other Contrib Module
                                             27
Friday, March 25, 2011
!
                                                                                    3,4-$*(
                                        8,$%"&-/(
                                                                                    9"#:(($-./*(
                                                                                    <%$=(
                                        !"#$%&'(
                   ;-#'*$(                                                          8,*#-$%"&-/(
                                                    9"#:(                           )"'(
                   ;-./*(
                                                    ;-./*(


                                                                       (
                                                             6*,/-7(
                                                    ;*+,(
                                                    )"'((
                                                    ;-./*(
                         )"'($"($*+,(
                         $-./*0(                                           !<-,,%&'(
                         (    1&2*#$(
                         (    3,4-$*(
                                                                           <%$=(>*#7(
                         (    5*/*$*(                                      2="#$()"?:(
                                                              28
Friday, March 25, 2011
!
                                pg_reorg
                                                                                    3,4-$*(
                                        8,$%"&-/(
                                                                                    9"#:(($-./*(
                                                                                    <%$=(
                                        !"#$%&'(
                   ;-#'*$(                                                          8,*#-$%"&-/(
                                                    9"#:(                           )"'(
                   ;-./*(
                                                    ;-./*(


                                                                       (
                                                             6*,/-7(
                                                    ;*+,(
                                                    )"'((
                                                    ;-./*(
                         )"'($"($*+,(
                         $-./*0(                                           !<-,,%&'(
                         (    1&2*#$(
                         (    3,4-$*(
                                                                           <%$=(>*#7(
                         (    5*/*$*(                                      2="#$()"?:(
                                                              28
Friday, March 25, 2011
29
Friday, March 25, 2011
pg_reorg Options
                           pg_reorg --no-order -table test -d omniti
                 -n
                  -- no-order
                 Do online VACUUM FULL.

                 -o columns [,...]
                 --order-by=columns [,...]
                 Do online CLUSTER ordered by specified columns.

                 -t table
                 --table=table

                 -Z
                 --no-analyze

                 -T seconds
                 --wait-timeout=seconds
                                                 29
Friday, March 25, 2011
30
Friday, March 25, 2011
pg_reorg in action
                         $ /opt/pgsql/bin/pg_reorg -e -t public.test --order-by=test_id -U postgres -d test

                 LOG: (query) SET statement_timeout = 0
                 LOG: (query) SET search_path = pg_catalog, pg_temp, public
                 LOG: (query) SET client_min_messages = warning
                 LOG: (query) SELECT * FROM reorg.tables WHERE relid = $1::regclass
                 LOG: (param:0) = public.test
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED

                 LOG: (query) SET LOCAL statement_timeout = 100
                 LOG: (query) LOCK TABLE test IN ACCESS EXCLUSIVE MODE
                 LOG: (query) RESET statement_timeout
                 LOG: (query) SELECT reorg.conflicted_triggers($1)
                 LOG: (param:0) = 7441636
                 LOG: (query) CREATE TYPE reorg.pk_7441636 AS (test_id integer)
                 LOG: (query) CREATE TABLE reorg.log_7441636 (id bigserial PRIMARY KEY, pk
                 reorg.pk_7441636, row pulbic.test)
                 LOG: (query) CREATE TRIGGER z_reorg_trigger BEFORE INSERT OR DELETE OR
                 UPDATE ON pulbic.test FOR EACH ROW EXECUTE PROCEDURE
                 reorg.reorg_trigger('INSERT INTO reorg.log_7441636(pk, row) VALUES( CASE
                 WHEN $1 IS NULL THEN NULL ELSE (ROW($1.test_id)::reorg.pk_7441636) END,
                 $2)')
                 LOG: (query) SELECT reorg.disable_autovacuum('reorg.log_7441636')
                 LOG: (query) COMMIT
                                                             30
Friday, March 25, 2011
pg_reorg in action
                         $ /opt/pgsql/bin/pg_reorg -e -t public.test --order-by=test_id -U postgres -d test

                 LOG: (query) SET statement_timeout = 0
                 LOG: (query) SET search_path = pg_catalog, pg_temp, public                             SET
                 LOG: (query) SET client_min_messages = warning
                 LOG: (query) SELECT * FROM reorg.tables WHERE relid = $1::regclass
                                                                                                      variables
                 LOG: (param:0) = public.test
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED

                 LOG: (query) SET LOCAL statement_timeout = 100
                 LOG: (query) LOCK TABLE test IN ACCESS EXCLUSIVE MODE
                 LOG: (query) RESET statement_timeout
                 LOG: (query) SELECT reorg.conflicted_triggers($1)
                 LOG: (param:0) = 7441636
                 LOG: (query) CREATE TYPE reorg.pk_7441636 AS (test_id integer)
                 LOG: (query) CREATE TABLE reorg.log_7441636 (id bigserial PRIMARY KEY, pk
                 reorg.pk_7441636, row pulbic.test)
                 LOG: (query) CREATE TRIGGER z_reorg_trigger BEFORE INSERT OR DELETE OR
                 UPDATE ON pulbic.test FOR EACH ROW EXECUTE PROCEDURE
                 reorg.reorg_trigger('INSERT INTO reorg.log_7441636(pk, row) VALUES( CASE
                 WHEN $1 IS NULL THEN NULL ELSE (ROW($1.test_id)::reorg.pk_7441636) END,
                 $2)')
                 LOG: (query) SELECT reorg.disable_autovacuum('reorg.log_7441636')
                 LOG: (query) COMMIT
                                                             30
Friday, March 25, 2011
pg_reorg in action
                         $ /opt/pgsql/bin/pg_reorg -e -t public.test --order-by=test_id -U postgres -d test

                 LOG: (query) SET statement_timeout = 0
                 LOG: (query) SET search_path = pg_catalog, pg_temp, public                             SET
                 LOG: (query) SET client_min_messages = warning
                 LOG: (query) SELECT * FROM reorg.tables WHERE relid = $1::regclass
                                                                                                      variables
                 LOG: (param:0) = public.test
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED

                 LOG: (query) SET LOCAL statement_timeout = 100
                 LOG: (query) LOCK TABLE test IN ACCESS EXCLUSIVE MODE
                 LOG: (query) RESET statement_timeout
                 LOG: (query) SELECT reorg.conflicted_triggers($1)
                                                                                     Place Triggers
                 LOG: (param:0) = 7441636
                 LOG: (query) CREATE TYPE reorg.pk_7441636 AS (test_id integer)
                 LOG: (query) CREATE TABLE reorg.log_7441636 (id bigserial PRIMARY KEY, pk
                 reorg.pk_7441636, row pulbic.test)
                 LOG: (query) CREATE TRIGGER z_reorg_trigger BEFORE INSERT OR DELETE OR
                 UPDATE ON pulbic.test FOR EACH ROW EXECUTE PROCEDURE
                 reorg.reorg_trigger('INSERT INTO reorg.log_7441636(pk, row) VALUES( CASE
                 WHEN $1 IS NULL THEN NULL ELSE (ROW($1.test_id)::reorg.pk_7441636) END,
                 $2)')
                 LOG: (query) SELECT reorg.disable_autovacuum('reorg.log_7441636')
                 LOG: (query) COMMIT
                                                             30
Friday, March 25, 2011
31
Friday, March 25, 2011
pg_reorg in action
                         LOG: (query) BEGIN ISOLATION LEVEL SERIALIZABLE
                 LOG: (query) SELECT set_config('work_mem', current_setting('maintenance_work_mem'),
                 true)
                 LOG: (query) SELECT reorg.array_accum(virtualtransaction) FROM pg_locks WHERE
                 locktype = 'virtualxid' AND pid <> pg_backend_pid()
                 LOG: (query) DELETE FROM reorg.log_7441636
                 LOG: (query) CREATE TABLE reorg.table_7441636 WITH (oids=false) TABLESPACE
                 pg_default AS SELECT * FROM ONLY public.test ORDER BY test_id
                 LOG: (query) SELECT reorg.disable_autovacuum('reorg.table_7441636')
                 LOG: (query) COMMIT
                 LOG: (query) SELECT indexrelid, reorg.reorg_indexdef(indexrelid, indrelid) FROM
                 pg_index WHERE indrelid = $1
                 LOG: (param:0) = 7441636
                 LOG: (query) CREATE UNIQUE INDEX index_201337719 ON reorg.table_7441636 USING
                 btree (test_id)

                 LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6)
                 LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1
                 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*)
                 LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id)
                 LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country,
                 state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE
                 (test_id) = ($1.test_id)
                 LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1
                 LOG: (param:5) = 1000                           31
Friday, March 25, 2011
pg_reorg in action
                         LOG: (query) BEGIN ISOLATION LEVEL SERIALIZABLE
                 LOG: (query) SELECT set_config('work_mem', current_setting('maintenance_work_mem'),
                 true)
                 LOG: (query) SELECT reorg.array_accum(virtualtransaction) FROM pg_locks WHERE
                 locktype = 'virtualxid' AND pid <> pg_backend_pid()                                 CTAS
                 LOG: (query) DELETE FROM reorg.log_7441636                                        Create
                 LOG: (query) CREATE TABLE reorg.table_7441636 WITH (oids=false) TABLESPACE
                 pg_default AS SELECT * FROM ONLY public.test ORDER BY test_id                    Indexes
                 LOG: (query) SELECT reorg.disable_autovacuum('reorg.table_7441636')
                 LOG: (query) COMMIT
                 LOG: (query) SELECT indexrelid, reorg.reorg_indexdef(indexrelid, indrelid) FROM
                 pg_index WHERE indrelid = $1
                 LOG: (param:0) = 7441636
                 LOG: (query) CREATE UNIQUE INDEX index_201337719 ON reorg.table_7441636 USING
                 btree (test_id)

                 LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6)
                 LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1
                 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*)
                 LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id)
                 LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country,
                 state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE
                 (test_id) = ($1.test_id)
                 LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1
                 LOG: (param:5) = 1000                           31
Friday, March 25, 2011
pg_reorg in action
                         LOG: (query) BEGIN ISOLATION LEVEL SERIALIZABLE
                 LOG: (query) SELECT set_config('work_mem', current_setting('maintenance_work_mem'),
                 true)
                 LOG: (query) SELECT reorg.array_accum(virtualtransaction) FROM pg_locks WHERE
                 locktype = 'virtualxid' AND pid <> pg_backend_pid()                                 CTAS
                 LOG: (query) DELETE FROM reorg.log_7441636                                        Create
                 LOG: (query) CREATE TABLE reorg.table_7441636 WITH (oids=false) TABLESPACE
                 pg_default AS SELECT * FROM ONLY public.test ORDER BY test_id                    Indexes
                 LOG: (query) SELECT reorg.disable_autovacuum('reorg.table_7441636')
                 LOG: (query) COMMIT
                 LOG: (query) SELECT indexrelid, reorg.reorg_indexdef(indexrelid, indrelid) FROM
                 pg_index WHERE indrelid = $1
                 LOG: (param:0) = 7441636
                 LOG: (query) CREATE UNIQUE INDEX index_201337719 ON reorg.table_7441636 USING
                 btree (test_id)
                                                                                                       Apply
                 LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6)
                 LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1               Operational
                 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*)                         logs
                 LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id)
                 LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country,
                 state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE
                 (test_id) = ($1.test_id)
                 LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1
                 LOG: (param:5) = 1000                           31
Friday, March 25, 2011
32
Friday, March 25, 2011
pg_reorg in action
                       LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED
                 LOG: (query) SET LOCAL statement_timeout = 100
                 LOG: (query) LOCK TABLE public.test IN ACCESS EXCLUSIVE MODE
                 LOG: (query) RESET statement_timeout
                 LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6)
                 LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1
                 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*)
                 LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id)
                 LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city,
                 country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr)
                 WHERE (test_id) = ($1.test_id)
                 LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1
                 LOG: (param:5) = 0

                 LOG: (query) SELECT reorg.reorg_swap($1)
                 LOG: (param:0) = 7441636
                 LOG: (query) COMMIT
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED

                 LOG: (query) SELECT reorg.reorg_drop($1)
                 LOG: (param:0) = 7441636
                 LOG: (query) COMMIT
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED
                 LOG: (query) ANALYZE publoc.test
                                                        32
                 LOG: (query) COMMIT
Friday, March 25, 2011
pg_reorg in action
                       LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED                                   Lock
                 LOG: (query) SET LOCAL statement_timeout = 100                                          table and
                 LOG: (query) LOCK TABLE public.test IN ACCESS EXCLUSIVE MODE                              apply
                 LOG: (query) RESET statement_timeout
                 LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6)                     operational logs
                 LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 last time
                 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*)
                 LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id)
                 LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city,
                 country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr)
                 WHERE (test_id) = ($1.test_id)
                 LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1
                 LOG: (param:5) = 0

                 LOG: (query) SELECT reorg.reorg_swap($1)
                 LOG: (param:0) = 7441636
                 LOG: (query) COMMIT
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED

                 LOG: (query) SELECT reorg.reorg_drop($1)
                 LOG: (param:0) = 7441636
                 LOG: (query) COMMIT
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED
                 LOG: (query) ANALYZE publoc.test
                                                        32
                 LOG: (query) COMMIT
Friday, March 25, 2011
pg_reorg in action
                       LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED                                   Lock
                 LOG: (query) SET LOCAL statement_timeout = 100                                          table and
                 LOG: (query) LOCK TABLE public.test IN ACCESS EXCLUSIVE MODE                              apply
                 LOG: (query) RESET statement_timeout
                 LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6)                     operational logs
                 LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 last time
                 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*)
                 LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id)
                 LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city,
                 country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr)
                 WHERE (test_id) = ($1.test_id)
                 LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1
                 LOG: (param:5) = 0

                 LOG: (query) SELECT reorg.reorg_swap($1)   Swapping
                 LOG: (param:0) = 7441636
                 LOG: (query) COMMIT
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED

                 LOG: (query) SELECT reorg.reorg_drop($1)
                 LOG: (param:0) = 7441636
                 LOG: (query) COMMIT
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED
                 LOG: (query) ANALYZE publoc.test
                                                        32
                 LOG: (query) COMMIT
Friday, March 25, 2011
pg_reorg in action
                       LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED                                   Lock
                 LOG: (query) SET LOCAL statement_timeout = 100                                          table and
                 LOG: (query) LOCK TABLE public.test IN ACCESS EXCLUSIVE MODE                              apply
                 LOG: (query) RESET statement_timeout
                 LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6)                     operational logs
                 LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 last time
                 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*)
                 LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id)
                 LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city,
                 country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr)
                 WHERE (test_id) = ($1.test_id)
                 LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1
                 LOG: (param:5) = 0

                 LOG: (query) SELECT reorg.reorg_swap($1)   Swapping
                 LOG: (param:0) = 7441636
                 LOG: (query) COMMIT
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED

                 LOG: (query) SELECT reorg.reorg_drop($1)                              Drop work and
                 LOG: (param:0) = 7441636                                               temp tables
                 LOG: (query) COMMIT
                 LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED
                                                                                      Analyze new table
                 LOG: (query) ANALYZE publoc.test
                                                        32
                 LOG: (query) COMMIT
Friday, March 25, 2011
33
Friday, March 25, 2011
pg_reorg in
                               Production
                     •Database Size 540GB
                     •OLTP database 2-3K transactions/sec
                     •Largest pre-rebuild table Size was
                         127GB

                         •Took 5.75 hours to rebuild
                         •Reclaimed 52GB
                         •No outage reported for website!
                                         33
Friday, March 25, 2011
34
Friday, March 25, 2011
pg_reorg in
                               Production
                    Table Size Before     Pg_Reorg
                                                         Bloat Removed
                         Reorg          Execution time

                         35GB            24m 10sec           13GB

                         27GB            116m 8 Sec          6GB

                         31GB            64m 32sec           4GB

                         44GB            128m 44sec          3GB

                                           34
Friday, March 25, 2011
35
Friday, March 25, 2011
35
Friday, March 25, 2011
36
Friday, March 25, 2011
36
Friday, March 25, 2011
37
Friday, March 25, 2011
Test Case

     • Database : PostgreSQL 9.0.2
     • OS: Solaris 11
     • RAM : 32GB
                                                         postgres=# d users
     • work_mem=16MB                                             Table "public.users"
                                             Column |                Type          | Modifiers
     • Table Name : Users                 --------------+--------------------------+-----------
                                            user_id       | integer                 | not null
     • Table Size : 1180 MB                       name           | text                 |
                                            creation_tsz | timestamp with time zone |
     • Indexes Size : 256 MB                     active        | boolean                 |
                                                clicks       | double precision            |
     • Rows : 6M                                                 Indexes:
                                           "users_pkey" PRIMARY KEY, btree (user_id)
                                             "users_creation_tsz" btree (creation_tsz)
                                                        - DELETE 3M ROWS
                                     37                 - UPDATE 1M ROWS
Friday, March 25, 2011
38
Friday, March 25, 2011
Comparison

                   CLUSTER             VACUUM FULL            PG_REORG

                    Execution Time:        Execution Time:      Execution Time:
                         2 min              1 min 50 Sec          1 min 4 Sec
                   Table Size: 594MB      Table Size: 594MB    Table Size: 594MB
                  Index Size: 128 MB     Index Size: 128 MB   Index Size: 128 MB



                          offline             offline               online


                         Built - in         Built-in          External Tool

                                                38
Friday, March 25, 2011
39
Friday, March 25, 2011
Other Tips

                     •Remove unused indexes
                     •Reindex indexes as needed
                     •Partitioned table
                      •Detach child table -> Cluster child
                         table -> Attach

                     •Avoid vacuum full (Pre PostgrSQL 9.0)
                                           39
Friday, March 25, 2011
40
Friday, March 25, 2011
Monitoring

                     •Circonus
                     •Nagios monitoring
                     •Bloat report


                                     40
Friday, March 25, 2011
41
Friday, March 25, 2011
trending


                     •Cacti
                     •Circonus


                                 41
Friday, March 25, 2011
42
Friday, March 25, 2011
trending




                            42
Friday, March 25, 2011
trending




                            42
Friday, March 25, 2011
43
Friday, March 25, 2011
thanks!

                     •OmniTi
                      •Robert Treat
                      •Depesz
                     •Joshua (End Point)
                     •PGEast Conference Committee

                                     43
Friday, March 25, 2011
44
Friday, March 25, 2011
References
                     •http://www.postgresql.org/docs/9.0/
                     •http://reorg.projects.postgresql.org/
                         pg_reorg.html

                     •https://labs.omniti.com/pgtreats/trunk/
                         tools/compact_table

                     •http://blog.endpoint.com/2010/09/
                         reducing-bloat-without-locking.html


                                         44
Friday, March 25, 2011
45
Friday, March 25, 2011
open discussion

                     •When PostgreSQL will have built in
                         features to rebuild table and index
                         online ?

                     •Is it worth to change MVCC handling
                         to avoid bloating?



                                          45
Friday, March 25, 2011
46
Friday, March 25, 2011
Questions?


                     •Email : denish@omniti.com
                     •Twitter : http://twitter.com/#!/denishpatel


                                          46
Friday, March 25, 2011

More Related Content

Viewers also liked

An Overview of Designing Microservices Based Applications on AWS - March 2017...
An Overview of Designing Microservices Based Applications on AWS - March 2017...An Overview of Designing Microservices Based Applications on AWS - March 2017...
An Overview of Designing Microservices Based Applications on AWS - March 2017...Amazon Web Services
 
LinkedIn Q4 2015 Earnings Call
LinkedIn Q4 2015 Earnings CallLinkedIn Q4 2015 Earnings Call
LinkedIn Q4 2015 Earnings CallLinkedIn
 
Dear NSA, let me take care of your slides.
Dear NSA, let me take care of your slides.Dear NSA, let me take care of your slides.
Dear NSA, let me take care of your slides.Emiland
 
UX, ethnography and possibilities: for Libraries, Museums and Archives
UX, ethnography and possibilities: for Libraries, Museums and ArchivesUX, ethnography and possibilities: for Libraries, Museums and Archives
UX, ethnography and possibilities: for Libraries, Museums and ArchivesNed Potter
 
Visual Design with Data
Visual Design with DataVisual Design with Data
Visual Design with DataSeth Familian
 

Viewers also liked (6)

An Overview of Designing Microservices Based Applications on AWS - March 2017...
An Overview of Designing Microservices Based Applications on AWS - March 2017...An Overview of Designing Microservices Based Applications on AWS - March 2017...
An Overview of Designing Microservices Based Applications on AWS - March 2017...
 
LinkedIn Q4 2015 Earnings Call
LinkedIn Q4 2015 Earnings CallLinkedIn Q4 2015 Earnings Call
LinkedIn Q4 2015 Earnings Call
 
How To Win That Next Sales Presentation - @High_Spark @cliffatkinson
How To Win That Next Sales Presentation - @High_Spark @cliffatkinsonHow To Win That Next Sales Presentation - @High_Spark @cliffatkinson
How To Win That Next Sales Presentation - @High_Spark @cliffatkinson
 
Dear NSA, let me take care of your slides.
Dear NSA, let me take care of your slides.Dear NSA, let me take care of your slides.
Dear NSA, let me take care of your slides.
 
UX, ethnography and possibilities: for Libraries, Museums and Archives
UX, ethnography and possibilities: for Libraries, Museums and ArchivesUX, ethnography and possibilities: for Libraries, Museums and Archives
UX, ethnography and possibilities: for Libraries, Museums and Archives
 
Visual Design with Data
Visual Design with DataVisual Design with Data
Visual Design with Data
 

Similar to Database Bloat Removal Techniques

Oscon2011 tutorial
Oscon2011 tutorialOscon2011 tutorial
Oscon2011 tutorialjtimberman
 
Governing services, data, rules, processes and more
Governing services, data, rules, processes and moreGoverning services, data, rules, processes and more
Governing services, data, rules, processes and moreRandall Hauch
 
Getting started with MySQL
Getting started with MySQLGetting started with MySQL
Getting started with MySQLJohn Ashmead
 
The State of Front End Web Development 2011
The State of Front End Web Development 2011The State of Front End Web Development 2011
The State of Front End Web Development 2011Pascal Rettig
 
MySQL Breakfast in London - 24 June 2010
MySQL Breakfast in London - 24 June 2010MySQL Breakfast in London - 24 June 2010
MySQL Breakfast in London - 24 June 2010Ivan Zoratti
 
Is Advanced Verification for FPGA based Logic needed
Is Advanced Verification for FPGA based Logic neededIs Advanced Verification for FPGA based Logic needed
Is Advanced Verification for FPGA based Logic neededchiportal
 
MySQL DW Breakfast
MySQL DW BreakfastMySQL DW Breakfast
MySQL DW BreakfastIvan Zoratti
 
A Case Study of NoSQL Adoption: What Drove Wordnik Non-Relational?
A Case Study of NoSQL Adoption: What Drove Wordnik Non-Relational?A Case Study of NoSQL Adoption: What Drove Wordnik Non-Relational?
A Case Study of NoSQL Adoption: What Drove Wordnik Non-Relational?DATAVERSITY
 
2012.10.20 OSC 2012 Hiroshima
2012.10.20 OSC 2012 Hiroshima2012.10.20 OSC 2012 Hiroshima
2012.10.20 OSC 2012 HiroshimaRyusuke Kajiyama
 
Drizzle 7.0, Future of Virtualizing
Drizzle 7.0, Future of VirtualizingDrizzle 7.0, Future of Virtualizing
Drizzle 7.0, Future of VirtualizingBrian Aker
 
Why would I store my data in more than one database?
Why would I store my data in more than one database?Why would I store my data in more than one database?
Why would I store my data in more than one database?Kurtosys Systems
 
Nosql from java developer pov
Nosql from java developer povNosql from java developer pov
Nosql from java developer povRoman Pichlík
 
50 Shades of Fail KScope16
50 Shades of Fail KScope1650 Shades of Fail KScope16
50 Shades of Fail KScope16Christian Berg
 
elns-the-opinions-of-physical-chemists_tcm18-244630.pptx
elns-the-opinions-of-physical-chemists_tcm18-244630.pptxelns-the-opinions-of-physical-chemists_tcm18-244630.pptx
elns-the-opinions-of-physical-chemists_tcm18-244630.pptxAlandraKahl1
 
Integrating ECM (WebCenter Content) with your Enterprise! 5 Tips to Try, 5 Tr...
Integrating ECM (WebCenter Content) with your Enterprise! 5 Tips to Try, 5 Tr...Integrating ECM (WebCenter Content) with your Enterprise! 5 Tips to Try, 5 Tr...
Integrating ECM (WebCenter Content) with your Enterprise! 5 Tips to Try, 5 Tr...Brian Huff
 
What Drove Wordnik Non-Relational?
What Drove Wordnik Non-Relational?What Drove Wordnik Non-Relational?
What Drove Wordnik Non-Relational?DATAVERSITY
 
Anthony Molinaro, OpenX, Erlang LA Meetup Slides
Anthony Molinaro, OpenX, Erlang LA Meetup SlidesAnthony Molinaro, OpenX, Erlang LA Meetup Slides
Anthony Molinaro, OpenX, Erlang LA Meetup SlidesMatthew Sacks
 
A data driven etl test framework sqlsat madison
A data driven etl test framework sqlsat madisonA data driven etl test framework sqlsat madison
A data driven etl test framework sqlsat madisonTerry Bunio
 

Similar to Database Bloat Removal Techniques (20)

Oscon2011 tutorial
Oscon2011 tutorialOscon2011 tutorial
Oscon2011 tutorial
 
Governing services, data, rules, processes and more
Governing services, data, rules, processes and moreGoverning services, data, rules, processes and more
Governing services, data, rules, processes and more
 
Getting started with MySQL
Getting started with MySQLGetting started with MySQL
Getting started with MySQL
 
The State of Front End Web Development 2011
The State of Front End Web Development 2011The State of Front End Web Development 2011
The State of Front End Web Development 2011
 
Coding Potpourri: MySQL
Coding Potpourri: MySQLCoding Potpourri: MySQL
Coding Potpourri: MySQL
 
MySQL Breakfast in London - 24 June 2010
MySQL Breakfast in London - 24 June 2010MySQL Breakfast in London - 24 June 2010
MySQL Breakfast in London - 24 June 2010
 
Is Advanced Verification for FPGA based Logic needed
Is Advanced Verification for FPGA based Logic neededIs Advanced Verification for FPGA based Logic needed
Is Advanced Verification for FPGA based Logic needed
 
MySQL DW Breakfast
MySQL DW BreakfastMySQL DW Breakfast
MySQL DW Breakfast
 
A Case Study of NoSQL Adoption: What Drove Wordnik Non-Relational?
A Case Study of NoSQL Adoption: What Drove Wordnik Non-Relational?A Case Study of NoSQL Adoption: What Drove Wordnik Non-Relational?
A Case Study of NoSQL Adoption: What Drove Wordnik Non-Relational?
 
2012.10.20 OSC 2012 Hiroshima
2012.10.20 OSC 2012 Hiroshima2012.10.20 OSC 2012 Hiroshima
2012.10.20 OSC 2012 Hiroshima
 
Drizzle 7.0, Future of Virtualizing
Drizzle 7.0, Future of VirtualizingDrizzle 7.0, Future of Virtualizing
Drizzle 7.0, Future of Virtualizing
 
Why would I store my data in more than one database?
Why would I store my data in more than one database?Why would I store my data in more than one database?
Why would I store my data in more than one database?
 
Nosql from java developer pov
Nosql from java developer povNosql from java developer pov
Nosql from java developer pov
 
50 Shades of Fail KScope16
50 Shades of Fail KScope1650 Shades of Fail KScope16
50 Shades of Fail KScope16
 
elns-the-opinions-of-physical-chemists_tcm18-244630.pptx
elns-the-opinions-of-physical-chemists_tcm18-244630.pptxelns-the-opinions-of-physical-chemists_tcm18-244630.pptx
elns-the-opinions-of-physical-chemists_tcm18-244630.pptx
 
Integrating ECM (WebCenter Content) with your Enterprise! 5 Tips to Try, 5 Tr...
Integrating ECM (WebCenter Content) with your Enterprise! 5 Tips to Try, 5 Tr...Integrating ECM (WebCenter Content) with your Enterprise! 5 Tips to Try, 5 Tr...
Integrating ECM (WebCenter Content) with your Enterprise! 5 Tips to Try, 5 Tr...
 
What Drove Wordnik Non-Relational?
What Drove Wordnik Non-Relational?What Drove Wordnik Non-Relational?
What Drove Wordnik Non-Relational?
 
Breaking data
Breaking dataBreaking data
Breaking data
 
Anthony Molinaro, OpenX, Erlang LA Meetup Slides
Anthony Molinaro, OpenX, Erlang LA Meetup SlidesAnthony Molinaro, OpenX, Erlang LA Meetup Slides
Anthony Molinaro, OpenX, Erlang LA Meetup Slides
 
A data driven etl test framework sqlsat madison
A data driven etl test framework sqlsat madisonA data driven etl test framework sqlsat madison
A data driven etl test framework sqlsat madison
 

More from Denish Patel

Out of the Box Replication in Postgres 9.4(PgConfUS)
Out of the Box Replication in Postgres 9.4(PgConfUS)Out of the Box Replication in Postgres 9.4(PgConfUS)
Out of the Box Replication in Postgres 9.4(PgConfUS)Denish Patel
 
Out of the box replication in postgres 9.4(pg confus)
Out of the box replication in postgres 9.4(pg confus)Out of the box replication in postgres 9.4(pg confus)
Out of the box replication in postgres 9.4(pg confus)Denish Patel
 
Out of the Box Replication in Postgres 9.4(pgconfsf)
Out of the Box Replication in Postgres 9.4(pgconfsf)Out of the Box Replication in Postgres 9.4(pgconfsf)
Out of the Box Replication in Postgres 9.4(pgconfsf)Denish Patel
 
Out of the Box Replication in Postgres 9.4(PgCon)
Out of the Box Replication in Postgres 9.4(PgCon)Out of the Box Replication in Postgres 9.4(PgCon)
Out of the Box Replication in Postgres 9.4(PgCon)Denish Patel
 
Out of the Box Replication in Postgres 9.4(PgCon)
Out of the Box Replication in Postgres 9.4(PgCon)Out of the Box Replication in Postgres 9.4(PgCon)
Out of the Box Replication in Postgres 9.4(PgCon)Denish Patel
 
Out of the box replication in postgres 9.4
Out of the box replication in postgres 9.4Out of the box replication in postgres 9.4
Out of the box replication in postgres 9.4Denish Patel
 
Choosing the "D" , Lightning talk
Choosing the "D" , Lightning talkChoosing the "D" , Lightning talk
Choosing the "D" , Lightning talkDenish Patel
 
Deploying postgre sql on amazon ec2
Deploying postgre sql on amazon ec2 Deploying postgre sql on amazon ec2
Deploying postgre sql on amazon ec2 Denish Patel
 
Two Elephants Inthe Room
Two Elephants Inthe RoomTwo Elephants Inthe Room
Two Elephants Inthe RoomDenish Patel
 
Deploying Maximum HA Architecture With PostgreSQL
Deploying Maximum HA Architecture With PostgreSQLDeploying Maximum HA Architecture With PostgreSQL
Deploying Maximum HA Architecture With PostgreSQLDenish Patel
 
Deploying Maximum HA Architecture With PostgreSQL
Deploying Maximum HA Architecture With PostgreSQLDeploying Maximum HA Architecture With PostgreSQL
Deploying Maximum HA Architecture With PostgreSQLDenish Patel
 
Achieving Pci Compliace
Achieving Pci CompliaceAchieving Pci Compliace
Achieving Pci CompliaceDenish Patel
 
Using SQL Standards? Database SQL comparition
Using SQL Standards? Database SQL comparitionUsing SQL Standards? Database SQL comparition
Using SQL Standards? Database SQL comparitionDenish Patel
 
Oracle10g New Features I
Oracle10g New Features IOracle10g New Features I
Oracle10g New Features IDenish Patel
 
Yet Another Replication Tool: RubyRep
Yet Another Replication Tool: RubyRepYet Another Replication Tool: RubyRep
Yet Another Replication Tool: RubyRepDenish Patel
 

More from Denish Patel (16)

Out of the Box Replication in Postgres 9.4(PgConfUS)
Out of the Box Replication in Postgres 9.4(PgConfUS)Out of the Box Replication in Postgres 9.4(PgConfUS)
Out of the Box Replication in Postgres 9.4(PgConfUS)
 
Out of the box replication in postgres 9.4(pg confus)
Out of the box replication in postgres 9.4(pg confus)Out of the box replication in postgres 9.4(pg confus)
Out of the box replication in postgres 9.4(pg confus)
 
Out of the Box Replication in Postgres 9.4(pgconfsf)
Out of the Box Replication in Postgres 9.4(pgconfsf)Out of the Box Replication in Postgres 9.4(pgconfsf)
Out of the Box Replication in Postgres 9.4(pgconfsf)
 
Out of the Box Replication in Postgres 9.4(PgCon)
Out of the Box Replication in Postgres 9.4(PgCon)Out of the Box Replication in Postgres 9.4(PgCon)
Out of the Box Replication in Postgres 9.4(PgCon)
 
Out of the Box Replication in Postgres 9.4(PgCon)
Out of the Box Replication in Postgres 9.4(PgCon)Out of the Box Replication in Postgres 9.4(PgCon)
Out of the Box Replication in Postgres 9.4(PgCon)
 
Out of the box replication in postgres 9.4
Out of the box replication in postgres 9.4Out of the box replication in postgres 9.4
Out of the box replication in postgres 9.4
 
Choosing the "D" , Lightning talk
Choosing the "D" , Lightning talkChoosing the "D" , Lightning talk
Choosing the "D" , Lightning talk
 
Scaling postgres
Scaling postgresScaling postgres
Scaling postgres
 
Deploying postgre sql on amazon ec2
Deploying postgre sql on amazon ec2 Deploying postgre sql on amazon ec2
Deploying postgre sql on amazon ec2
 
Two Elephants Inthe Room
Two Elephants Inthe RoomTwo Elephants Inthe Room
Two Elephants Inthe Room
 
Deploying Maximum HA Architecture With PostgreSQL
Deploying Maximum HA Architecture With PostgreSQLDeploying Maximum HA Architecture With PostgreSQL
Deploying Maximum HA Architecture With PostgreSQL
 
Deploying Maximum HA Architecture With PostgreSQL
Deploying Maximum HA Architecture With PostgreSQLDeploying Maximum HA Architecture With PostgreSQL
Deploying Maximum HA Architecture With PostgreSQL
 
Achieving Pci Compliace
Achieving Pci CompliaceAchieving Pci Compliace
Achieving Pci Compliace
 
Using SQL Standards? Database SQL comparition
Using SQL Standards? Database SQL comparitionUsing SQL Standards? Database SQL comparition
Using SQL Standards? Database SQL comparition
 
Oracle10g New Features I
Oracle10g New Features IOracle10g New Features I
Oracle10g New Features I
 
Yet Another Replication Tool: RubyRep
Yet Another Replication Tool: RubyRepYet Another Replication Tool: RubyRep
Yet Another Replication Tool: RubyRep
 

Database Bloat Removal Techniques

  • 2. Your Database!! Denish Patel Database Architect OmniTi Computer Consulting Inc. denish@omniti.com 1 Friday, March 25, 2011
  • 4. Who am I ? • Denish Patel • Database Architect • 4+ Years with OmniTi • Expertise • Heterogeneous Databases • PostgreSQL, Oracle, MySQL • Very Large databases • Performance tuning • Application level • SQL tuning • Database and OS parameters • Objects tuning 2 Friday, March 25, 2011
  • 5. Who am I ? • Denish Patel • Database Architect • 4+ Years with OmniTi • Expertise • Heterogeneous Databases • PostgreSQL, Oracle, MySQL • Very Large databases • Performance tuning • Application level OmniTi is hiring! • SQL tuning • Database and OS parameters • Objects tuning 2 Friday, March 25, 2011
  • 7. Agenda •Why bloat ? •Issues •Identify bloat •Tables •Indexes •Bloat removal toolkit •Monitoring and trending 3 Friday, March 25, 2011
  • 9. why bloat? •MVCC •ACID •Updates & Deletes 4 Friday, March 25, 2011
  • 11. MVCC method-1 5 Friday, March 25, 2011
  • 12. MVCC method-1 5 Friday, March 25, 2011
  • 13. MVCC method-1 ! 34..-+56'' ' !:723,' 7$89$"&' !"#$%&' ,+-.$' /+&+' (0/1,2' ()*+&$ ><??!,' ' /2;2,2' 72;2>,'' ,31:7' ;<=' 5 Friday, March 25, 2011
  • 15. MVCC method-2 6 Friday, March 25, 2011
  • 16. MVCC method-2 6 Friday, March 25, 2011
  • 17. MVCC method-2 ! & 3./,-!& !"#$%& /,0,4!&& '"("& )*'+!,& !-+./& ',0,!,& 012& 41553!& 6 Friday, March 25, 2011
  • 19. Issues •Unnecessary costly I/O operations •Poor database tables access time •Increase maintenance time •Waste of resources •RAM •CPU •Disk 7 Friday, March 25, 2011
  • 21. Prevent Bloat • autovacuum =on • vacuum manually between batch updates • Truncate table • Free Space Map • <= PostgreSQL 8.3 • max_fsm_pages • max_fsm_tables • >=PostgreSQL 8.4 • auto sizing free space map 8 Friday, March 25, 2011
  • 23. BEWARE! • Bug: long running auto-vacuum workers • PostgreSQL Version Affected • 8.3.10 • 8.3.11 • 8.3.12 • 8.4.4 • 8.4.5 9 Friday, March 25, 2011
  • 24. BEWARE! • Bug: long running auto-vacuum workers • PostgreSQL Version Affected • 8.3.10 • 8.3.11 • 8.3.12 • 8.4.4 • 8.4.5 Upgrade to latest release !! 9 Friday, March 25, 2011
  • 26. Measure Bloat •Bloat Report •pg_bloat_report (OmniTI Labs) •Nagios Monitoring •Check_postgres_bloat 10 Friday, March 25, 2011
  • 28. pg_bloat_report Bloat Report Tables 1. omniti.hits 1969348 of 4255960 pages wasted (46.3%), 15 GB of 32 GB. 2. omniti.clients 279979 of 370509 pages wasted (75.6%), 2187 MB of 2895 MB. Bloat Report Indexes 1. omniti.hits_pk 51275 of 71075 pages wasted (72.1%), 401 MB of 555 MB. 2. omniti.clients_tz 47550 of 71271 pages wasted (66.7%), 371 MB 11 557 MB. of Friday, March 25, 2011
  • 30. check_postgres_bloat Notification Type: PROBLEM Host: omniti State: CRITICAL Date/Time: Wed Feb 16 11:24:56 UTC 2011 Additional Info: POSTGRES_BLOAT CRITICAL: DB "omniti" (host:omniti) (port=5432) table omniti.hits rows:23995164 pages:2858893 shouldbe:2278176 (1.3X) wasted size:4757233664 (4 GB) 12 Friday, March 25, 2011
  • 32. bloat removal toolkit • Offline - with locking • Vacuum • Vacuum Full • Cluster • Cluster vs Vacuum Full • Online - with minimal locking • compact_table • pg_reorg 13 Friday, March 25, 2011
  • 36. vacuum • Auto vacuum • VACUUM [verbose|analyze] table • Reclaims storage occupied by dead tuples • Reclaimed space available to re-use • Normally free space doesn’t return to OS • No exclusive table lock 15 Friday, March 25, 2011
  • 38. vacuum full • VACUUM FULL table • Compact table based on dead rows • Starting PostgreSQL 9.0 , it’s rewrite entire table and indexes (like CLUSTER) • Reclaimed space available to re-use • Space returned to OS • Table Exclusive lock • Expensive operation 16 Friday, March 25, 2011
  • 42. cluster •CLUSTER [verbose] table_name [USING index_name] •Create reorganized copy of table based on index •Rebuild indexes too •Requires Exclusive Lock on table •Expensive Operation 18 Friday, March 25, 2011
  • 44. cluster vs vacuum full It’s just rewrite of table without Order based on Index any specific order Table needs index Doesn’t need index Bloat indexes (Pre PostgreSQL Doesn’t bloat index 9.0) Overall Operation Slower (Pre Overall operation Faster PostgreSQL 9.0) Recommended Not recommended 19 Friday, March 25, 2011
  • 48. compact_table •Developed by OmniTi •Reorganize rows to empty pages at the end based on ctid •ctid - (page number, tuple number) •When we update a row, the row's ctid changes, because the update creates a new version of the row and leaves the old version behind 21 Friday, March 25, 2011
  • 50. compact_table postgres=# select ctid,* from bar; ctid | a | b -------+---+--- (0,1) | 1 | 1 (0,2) | 2 | 1 (2 rows) postgres=# update bar set a=3 where a=2; UPDATE 1 postgres=# select ctid,* from bar; ctid | a | b -------+---+--- (0,1) | 1 | 1 (0,3) | 3 | 1 (2 rows) postgres=# vacuum verbose bar; . . INFO: "bar": found 1 removable, 2 nonremovable row versions in 1 out of 1 pages DETAIL: 0 dead row versions cannot be removed yet. VACUUM 22 Friday, March 25, 2011
  • 52. compact_table 23 Friday, March 25, 2011
  • 53. compact_table postgres=# truncate table bar; TRUNCATE TABLE postgres=# insert into bar select generate_series(1,1000); INSERT 0 1000 postgres=# delete from bar where a %2 = 0; DELETE 500 postgres=# select max(ctid) from bar; max -------- (4,95) (1 row) postgres=# vacuum verbose bar; INFO: "bar": found 0 removable, 500 nonremovable row versions in 5 out of 5 pages VACUUM 23 Friday, March 25, 2011
  • 55. compact_table postgres=# begin; BEGIN postgres=# update bar set a=a where ctid>='(3,0)'; UPDATE 161 postgres=# update bar set a=a where ctid>='(3,0)'; UPDATE 161 postgres=# update bar set a=a where ctid>='(3,0)'; UPDATE 48 postgres=# update bar set a=a where ctid>='(3,0)'; UPDATE 48 postgres=# update bar set a=a where ctid>='(3,0)'; UPDATE 34 postgres=# update bar set a=a where ctid>='(3,0)'; UPDATE 0 postgres=# commit; COMMIT postgres=# vacuum verbose bar; . . INFO: "bar": truncated 5 to 3 pages . VACUUM 24 Friday, March 25, 2011
  • 57. compact_table •Pretty safe update process •No additional changes required •Slow process •Generate Index bloat •Under development •Not tested in production •Future consideration? 25 Friday, March 25, 2011
  • 61. pg_reorg • Developed by NTT OSS Center • Reorganize table with very short lock • Needs Primary Key • Not Null Unique Key works! • CLUSTER online • ORDER BY Key • VACUUM FULL Online • Rewrite without ORDER BY • Build and Install like other Contrib Module 27 Friday, March 25, 2011
  • 62. ! 3,4-$*( 8,$%"&-/( 9"#:(($-./*( <%$=( !"#$%&'( ;-#'*$( 8,*#-$%"&-/( 9"#:( )"'( ;-./*( ;-./*( ( 6*,/-7( ;*+,( )"'(( ;-./*( )"'($"($*+,( $-./*0( !<-,,%&'( ( 1&2*#$( ( 3,4-$*( <%$=(>*#7( ( 5*/*$*( 2="#$()"?:( 28 Friday, March 25, 2011
  • 63. ! pg_reorg 3,4-$*( 8,$%"&-/( 9"#:(($-./*( <%$=( !"#$%&'( ;-#'*$( 8,*#-$%"&-/( 9"#:( )"'( ;-./*( ;-./*( ( 6*,/-7( ;*+,( )"'(( ;-./*( )"'($"($*+,( $-./*0( !<-,,%&'( ( 1&2*#$( ( 3,4-$*( <%$=(>*#7( ( 5*/*$*( 2="#$()"?:( 28 Friday, March 25, 2011
  • 65. pg_reorg Options pg_reorg --no-order -table test -d omniti -n -- no-order Do online VACUUM FULL. -o columns [,...] --order-by=columns [,...] Do online CLUSTER ordered by specified columns. -t table --table=table -Z --no-analyze -T seconds --wait-timeout=seconds 29 Friday, March 25, 2011
  • 67. pg_reorg in action $ /opt/pgsql/bin/pg_reorg -e -t public.test --order-by=test_id -U postgres -d test LOG: (query) SET statement_timeout = 0 LOG: (query) SET search_path = pg_catalog, pg_temp, public LOG: (query) SET client_min_messages = warning LOG: (query) SELECT * FROM reorg.tables WHERE relid = $1::regclass LOG: (param:0) = public.test LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) SET LOCAL statement_timeout = 100 LOG: (query) LOCK TABLE test IN ACCESS EXCLUSIVE MODE LOG: (query) RESET statement_timeout LOG: (query) SELECT reorg.conflicted_triggers($1) LOG: (param:0) = 7441636 LOG: (query) CREATE TYPE reorg.pk_7441636 AS (test_id integer) LOG: (query) CREATE TABLE reorg.log_7441636 (id bigserial PRIMARY KEY, pk reorg.pk_7441636, row pulbic.test) LOG: (query) CREATE TRIGGER z_reorg_trigger BEFORE INSERT OR DELETE OR UPDATE ON pulbic.test FOR EACH ROW EXECUTE PROCEDURE reorg.reorg_trigger('INSERT INTO reorg.log_7441636(pk, row) VALUES( CASE WHEN $1 IS NULL THEN NULL ELSE (ROW($1.test_id)::reorg.pk_7441636) END, $2)') LOG: (query) SELECT reorg.disable_autovacuum('reorg.log_7441636') LOG: (query) COMMIT 30 Friday, March 25, 2011
  • 68. pg_reorg in action $ /opt/pgsql/bin/pg_reorg -e -t public.test --order-by=test_id -U postgres -d test LOG: (query) SET statement_timeout = 0 LOG: (query) SET search_path = pg_catalog, pg_temp, public SET LOG: (query) SET client_min_messages = warning LOG: (query) SELECT * FROM reorg.tables WHERE relid = $1::regclass variables LOG: (param:0) = public.test LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) SET LOCAL statement_timeout = 100 LOG: (query) LOCK TABLE test IN ACCESS EXCLUSIVE MODE LOG: (query) RESET statement_timeout LOG: (query) SELECT reorg.conflicted_triggers($1) LOG: (param:0) = 7441636 LOG: (query) CREATE TYPE reorg.pk_7441636 AS (test_id integer) LOG: (query) CREATE TABLE reorg.log_7441636 (id bigserial PRIMARY KEY, pk reorg.pk_7441636, row pulbic.test) LOG: (query) CREATE TRIGGER z_reorg_trigger BEFORE INSERT OR DELETE OR UPDATE ON pulbic.test FOR EACH ROW EXECUTE PROCEDURE reorg.reorg_trigger('INSERT INTO reorg.log_7441636(pk, row) VALUES( CASE WHEN $1 IS NULL THEN NULL ELSE (ROW($1.test_id)::reorg.pk_7441636) END, $2)') LOG: (query) SELECT reorg.disable_autovacuum('reorg.log_7441636') LOG: (query) COMMIT 30 Friday, March 25, 2011
  • 69. pg_reorg in action $ /opt/pgsql/bin/pg_reorg -e -t public.test --order-by=test_id -U postgres -d test LOG: (query) SET statement_timeout = 0 LOG: (query) SET search_path = pg_catalog, pg_temp, public SET LOG: (query) SET client_min_messages = warning LOG: (query) SELECT * FROM reorg.tables WHERE relid = $1::regclass variables LOG: (param:0) = public.test LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) SET LOCAL statement_timeout = 100 LOG: (query) LOCK TABLE test IN ACCESS EXCLUSIVE MODE LOG: (query) RESET statement_timeout LOG: (query) SELECT reorg.conflicted_triggers($1) Place Triggers LOG: (param:0) = 7441636 LOG: (query) CREATE TYPE reorg.pk_7441636 AS (test_id integer) LOG: (query) CREATE TABLE reorg.log_7441636 (id bigserial PRIMARY KEY, pk reorg.pk_7441636, row pulbic.test) LOG: (query) CREATE TRIGGER z_reorg_trigger BEFORE INSERT OR DELETE OR UPDATE ON pulbic.test FOR EACH ROW EXECUTE PROCEDURE reorg.reorg_trigger('INSERT INTO reorg.log_7441636(pk, row) VALUES( CASE WHEN $1 IS NULL THEN NULL ELSE (ROW($1.test_id)::reorg.pk_7441636) END, $2)') LOG: (query) SELECT reorg.disable_autovacuum('reorg.log_7441636') LOG: (query) COMMIT 30 Friday, March 25, 2011
  • 71. pg_reorg in action LOG: (query) BEGIN ISOLATION LEVEL SERIALIZABLE LOG: (query) SELECT set_config('work_mem', current_setting('maintenance_work_mem'), true) LOG: (query) SELECT reorg.array_accum(virtualtransaction) FROM pg_locks WHERE locktype = 'virtualxid' AND pid <> pg_backend_pid() LOG: (query) DELETE FROM reorg.log_7441636 LOG: (query) CREATE TABLE reorg.table_7441636 WITH (oids=false) TABLESPACE pg_default AS SELECT * FROM ONLY public.test ORDER BY test_id LOG: (query) SELECT reorg.disable_autovacuum('reorg.table_7441636') LOG: (query) COMMIT LOG: (query) SELECT indexrelid, reorg.reorg_indexdef(indexrelid, indrelid) FROM pg_index WHERE indrelid = $1 LOG: (param:0) = 7441636 LOG: (query) CREATE UNIQUE INDEX index_201337719 ON reorg.table_7441636 USING btree (test_id) LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6) LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*) LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id) LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE (test_id) = ($1.test_id) LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1 LOG: (param:5) = 1000 31 Friday, March 25, 2011
  • 72. pg_reorg in action LOG: (query) BEGIN ISOLATION LEVEL SERIALIZABLE LOG: (query) SELECT set_config('work_mem', current_setting('maintenance_work_mem'), true) LOG: (query) SELECT reorg.array_accum(virtualtransaction) FROM pg_locks WHERE locktype = 'virtualxid' AND pid <> pg_backend_pid() CTAS LOG: (query) DELETE FROM reorg.log_7441636 Create LOG: (query) CREATE TABLE reorg.table_7441636 WITH (oids=false) TABLESPACE pg_default AS SELECT * FROM ONLY public.test ORDER BY test_id Indexes LOG: (query) SELECT reorg.disable_autovacuum('reorg.table_7441636') LOG: (query) COMMIT LOG: (query) SELECT indexrelid, reorg.reorg_indexdef(indexrelid, indrelid) FROM pg_index WHERE indrelid = $1 LOG: (param:0) = 7441636 LOG: (query) CREATE UNIQUE INDEX index_201337719 ON reorg.table_7441636 USING btree (test_id) LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6) LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*) LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id) LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE (test_id) = ($1.test_id) LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1 LOG: (param:5) = 1000 31 Friday, March 25, 2011
  • 73. pg_reorg in action LOG: (query) BEGIN ISOLATION LEVEL SERIALIZABLE LOG: (query) SELECT set_config('work_mem', current_setting('maintenance_work_mem'), true) LOG: (query) SELECT reorg.array_accum(virtualtransaction) FROM pg_locks WHERE locktype = 'virtualxid' AND pid <> pg_backend_pid() CTAS LOG: (query) DELETE FROM reorg.log_7441636 Create LOG: (query) CREATE TABLE reorg.table_7441636 WITH (oids=false) TABLESPACE pg_default AS SELECT * FROM ONLY public.test ORDER BY test_id Indexes LOG: (query) SELECT reorg.disable_autovacuum('reorg.table_7441636') LOG: (query) COMMIT LOG: (query) SELECT indexrelid, reorg.reorg_indexdef(indexrelid, indrelid) FROM pg_index WHERE indrelid = $1 LOG: (param:0) = 7441636 LOG: (query) CREATE UNIQUE INDEX index_201337719 ON reorg.table_7441636 USING btree (test_id) Apply LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6) LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 Operational LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*) logs LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id) LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE (test_id) = ($1.test_id) LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1 LOG: (param:5) = 1000 31 Friday, March 25, 2011
  • 75. pg_reorg in action LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) SET LOCAL statement_timeout = 100 LOG: (query) LOCK TABLE public.test IN ACCESS EXCLUSIVE MODE LOG: (query) RESET statement_timeout LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6) LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*) LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id) LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE (test_id) = ($1.test_id) LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1 LOG: (param:5) = 0 LOG: (query) SELECT reorg.reorg_swap($1) LOG: (param:0) = 7441636 LOG: (query) COMMIT LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) SELECT reorg.reorg_drop($1) LOG: (param:0) = 7441636 LOG: (query) COMMIT LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) ANALYZE publoc.test 32 LOG: (query) COMMIT Friday, March 25, 2011
  • 76. pg_reorg in action LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED Lock LOG: (query) SET LOCAL statement_timeout = 100 table and LOG: (query) LOCK TABLE public.test IN ACCESS EXCLUSIVE MODE apply LOG: (query) RESET statement_timeout LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6) operational logs LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 last time LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*) LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id) LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE (test_id) = ($1.test_id) LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1 LOG: (param:5) = 0 LOG: (query) SELECT reorg.reorg_swap($1) LOG: (param:0) = 7441636 LOG: (query) COMMIT LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) SELECT reorg.reorg_drop($1) LOG: (param:0) = 7441636 LOG: (query) COMMIT LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) ANALYZE publoc.test 32 LOG: (query) COMMIT Friday, March 25, 2011
  • 77. pg_reorg in action LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED Lock LOG: (query) SET LOCAL statement_timeout = 100 table and LOG: (query) LOCK TABLE public.test IN ACCESS EXCLUSIVE MODE apply LOG: (query) RESET statement_timeout LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6) operational logs LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 last time LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*) LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id) LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE (test_id) = ($1.test_id) LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1 LOG: (param:5) = 0 LOG: (query) SELECT reorg.reorg_swap($1) Swapping LOG: (param:0) = 7441636 LOG: (query) COMMIT LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) SELECT reorg.reorg_drop($1) LOG: (param:0) = 7441636 LOG: (query) COMMIT LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) ANALYZE publoc.test 32 LOG: (query) COMMIT Friday, March 25, 2011
  • 78. pg_reorg in action LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED Lock LOG: (query) SET LOCAL statement_timeout = 100 table and LOG: (query) LOCK TABLE public.test IN ACCESS EXCLUSIVE MODE apply LOG: (query) RESET statement_timeout LOG: (query) SELECT reorg.reorg_apply($1, $2, $3, $4, $5, $6) operational logs LOG: (param:0) = SELECT * FROM reorg.log_7441636 ORDER BY id LIMIT $1 last time LOG: (param:1) = INSERT INTO reorg.table_7441636 VALUES ($1.*) LOG: (param:2) = DELETE FROM reorg.table_7441636 WHERE (test_id) = ($1.test_id) LOG: (param:3) = UPDATE reorg.table_7441636 SET (test_id, name, lat, lon, city, country, state_abr) = ($2.test_id, $2.name, $2.lat, $2.lon, $2.city, $2.country, $2.state_abr) WHERE (test_id) = ($1.test_id) LOG: (param:4) = DELETE FROM reorg.log_7441636 WHERE id <= $1 LOG: (param:5) = 0 LOG: (query) SELECT reorg.reorg_swap($1) Swapping LOG: (param:0) = 7441636 LOG: (query) COMMIT LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED LOG: (query) SELECT reorg.reorg_drop($1) Drop work and LOG: (param:0) = 7441636 temp tables LOG: (query) COMMIT LOG: (query) BEGIN ISOLATION LEVEL READ COMMITTED Analyze new table LOG: (query) ANALYZE publoc.test 32 LOG: (query) COMMIT Friday, March 25, 2011
  • 80. pg_reorg in Production •Database Size 540GB •OLTP database 2-3K transactions/sec •Largest pre-rebuild table Size was 127GB •Took 5.75 hours to rebuild •Reclaimed 52GB •No outage reported for website! 33 Friday, March 25, 2011
  • 82. pg_reorg in Production Table Size Before Pg_Reorg Bloat Removed Reorg Execution time 35GB 24m 10sec 13GB 27GB 116m 8 Sec 6GB 31GB 64m 32sec 4GB 44GB 128m 44sec 3GB 34 Friday, March 25, 2011
  • 88. Test Case • Database : PostgreSQL 9.0.2 • OS: Solaris 11 • RAM : 32GB postgres=# d users • work_mem=16MB Table "public.users" Column | Type | Modifiers • Table Name : Users --------------+--------------------------+----------- user_id | integer | not null • Table Size : 1180 MB name | text | creation_tsz | timestamp with time zone | • Indexes Size : 256 MB active | boolean | clicks | double precision | • Rows : 6M Indexes: "users_pkey" PRIMARY KEY, btree (user_id) "users_creation_tsz" btree (creation_tsz) - DELETE 3M ROWS 37 - UPDATE 1M ROWS Friday, March 25, 2011
  • 90. Comparison CLUSTER VACUUM FULL PG_REORG Execution Time: Execution Time: Execution Time: 2 min 1 min 50 Sec 1 min 4 Sec Table Size: 594MB Table Size: 594MB Table Size: 594MB Index Size: 128 MB Index Size: 128 MB Index Size: 128 MB offline offline online Built - in Built-in External Tool 38 Friday, March 25, 2011
  • 92. Other Tips •Remove unused indexes •Reindex indexes as needed •Partitioned table •Detach child table -> Cluster child table -> Attach •Avoid vacuum full (Pre PostgrSQL 9.0) 39 Friday, March 25, 2011
  • 94. Monitoring •Circonus •Nagios monitoring •Bloat report 40 Friday, March 25, 2011
  • 96. trending •Cacti •Circonus 41 Friday, March 25, 2011
  • 98. trending 42 Friday, March 25, 2011
  • 99. trending 42 Friday, March 25, 2011
  • 101. thanks! •OmniTi •Robert Treat •Depesz •Joshua (End Point) •PGEast Conference Committee 43 Friday, March 25, 2011
  • 103. References •http://www.postgresql.org/docs/9.0/ •http://reorg.projects.postgresql.org/ pg_reorg.html •https://labs.omniti.com/pgtreats/trunk/ tools/compact_table •http://blog.endpoint.com/2010/09/ reducing-bloat-without-locking.html 44 Friday, March 25, 2011
  • 105. open discussion •When PostgreSQL will have built in features to rebuild table and index online ? •Is it worth to change MVCC handling to avoid bloating? 45 Friday, March 25, 2011
  • 107. Questions? •Email : denish@omniti.com •Twitter : http://twitter.com/#!/denishpatel 46 Friday, March 25, 2011