Occasional Really Slow Running Updates/Inserts

From: Dave Stibrany <dstibrany(at)gmail(dot)com>
To: pgsql-performance(at)postgresql(dot)org
Subject: Occasional Really Slow Running Updates/Inserts
Date: 2015-09-17 19:14:43
Message-ID: CAK17JmnxS6mTNXELZiQGLAhS5vmFcv02cy0+7Qgum5JHeVKODw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-performance

Hi all. I am occasionally seeing really slow update/inserts into a fairly
large table. By really slow I mean around 10-40 seconds,
while the majority of queries take milliseconds. I cannot reproduce this
problem myself, but it is occurring multiple times a day
(maybe 30 times).

System Info
---------------
Model: Dell PowerEdge R420
CPU: 12 core Intel(R) Xeon(R) @ 2.20GHz
Memory: 16GB
Disk: PERC H310 Mini Raid Controller using Raid 1
OS: Ubuntu 14.04.3 LTS

DB Settings
----------------

name current_setting
source
-------------------------------+----------------------------------------+----------------------
application_name | psql
| client
auto_explain.log_min_duration | 15s |
configuration file
checkpoint_segments | 16
| configuration file
client_encoding | UTF8
| client
DateStyle | ISO, YMD
| configuration file
default_text_search_config | pg_catalog.english
| configuration file
effective_cache_size | 8GB
| configuration file
external_pid_file |
/var/run/postgresql/9.3-main.pid | configuration file
hot_standby | on
| configuration file
lc_messages | en_CA.UTF-8
| configuration file
lc_monetary | en_CA.UTF-8
| configuration file
lc_numeric | en_CA.UTF-8
| configuration file
lc_time | en_CA.UTF-8
| configuration file
listen_addresses | localhost,x.x.x.x
| configuration file
log_autovacuum_min_duration | -1 |
configuration file
log_checkpoints | on
| configuration file
log_line_prefix | %m %p %v %x
| configuration file
log_lock_waits | on
| configuration file
log_min_duration_statement | 15s |
configuration file
log_timezone | UTC
| configuration file
max_connections | 100
| configuration file
max_stack_depth | 2MB
| environment variable
max_wal_senders | 3
| configuration file
pg_stat_statements.track | all
| configuration file
shared_buffers | 4GB
| configuration file
shared_preload_libraries | pg_stat_statements, auto_explain
| configuration file
ssl | on
| configuration file
TimeZone | UTC
| configuration file
track_activity_query_size | 2048
| configuration file
unix_socket_directories | /var/run/postgresql
| configuration file
wal_keep_segments | 32
| configuration file
wal_level | hot_standby
| configuration file

Schema
-------

Table "public.documents"
Column | Type |
Modifiers
------------------------+-----------------------------+--------------------------------------------------------
id | bigint | not null
default nextval('documents_id_seq'::regclass)
user_id | bigint | not null
biller_id bigint | not null
filename | character varying(255) | not null
resource | character varying(255) | not null
size | integer | not
null
doc_type | character varying(255) | not null
content_type | character varying(255) | not null
account_name | character varying(255) |
account_number | character varying(255) |
bill_date | timestamp without time zone |
due_date | date |
amount | numeric(12,2) |
amount | numeric(12,2) |
amount | numeric(12,2) |
amount | numeric(12,2) |
amount | numeric(12,2) |
paid | boolean |
paid_date | timestamp without time zone |
paid_amount | numeric(12,2) |
contents | text |
contents_search | tsvector |
extra_data | text |
created_at | timestamp without time zone | not null default
now()
updated_at | timestamp without time zone | not null default now()
billercred_id | bigint |
folder_id | bigint |
shasum | character varying(255) |
intake_type | smallint | not null default 1
page_count | smallint |
notes | text |
vendor_name | character varying(255) |
invoice_number | character varying(255) |
tax | numeric(12,2) |
subtotal | numeric(12,2) |
payment_account_number | character varying(255) |
currency | character varying(3) |
payment_method | payment_method |
workflow_state | workflow_states | default
'review'::workflow_states
vendor_id | bigint |
document_type | document_types |
Indexes:
"documents_pkey" PRIMARY KEY, btree (id)
"document_search_ix" gin (contents_search)
"document_user_id_recvd_ix" btree (user_id, bill_date DESC)
Foreign-key constraints:
"documents_biller_id_fkey" FOREIGN KEY (biller_id) REFERENCES
billers(id) ON DELETE SET DEFAULT
"documents_billercred_id_fkey" FOREIGN KEY (billercred_id) REFERENCES
billercreds(id) ON DELETE SET NULL
"documents_folder_id_fkey" FOREIGN KEY (folder_id) REFERENCES
folders(id) ON DELETE CASCADE
"documents_user_id_fkey" FOREIGN KEY (user_id) REFERENCES users(id) ON
DELETE CASCADE
"documents_vendor_id_fkey" FOREIGN KEY (vendor_id) REFERENCES
vendors(id) ON DELETE SET NULL
Referenced by:
TABLE "document_billcom_actions" CONSTRAINT
"document_billcom_actions_document_id_fkey" FOREIGN KEY (document_id)
REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_box_actions" CONSTRAINT
"document_box_actions_document_id_fkey" FOREIGN KEY (document_id)
REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_email_forwarding_actions" CONSTRAINT
"document_email_forwarding_actions_document_id_fkey" FOREIGN KEY
(document_id) REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_qbo_actions" CONSTRAINT
"document_qbo_actions_document_id_fkey" FOREIGN KEY (document_id)
REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_xero_actions" CONSTRAINT
"document_xero_actions_document_id_fkey" FOREIGN KEY (document_id)
REFERENCES documents(id) ON DELETE CASCADE
TABLE "document_xerofiles_actions" CONSTRAINT
"document_xerofiles_actions_document_id_fkey" FOREIGN KEY (document_id)
REFERENCES documents(id) ON DELETE CASCADE
TABLE "documenttagmap" CONSTRAINT "documenttagmap_document_id_fkey"
FOREIGN KEY (document_id) REFERENCES documents(id) ON DELETE CASCADE
TABLE "synced_docs" CONSTRAINT "synced_docs_doc_id_fkey" FOREIGN KEY
(doc_id) REFERENCES documents(id) ON DELETE CASCADE
Triggers:
document_search_update BEFORE INSERT OR UPDATE ON documents FOR EACH
ROW EXECUTE PROCEDURE tsvector_update_trigger('contents_search',
'pg_catalog.english', 'contents', 'filename', 'account_name',
'account_number')
document_updated_at_t BEFORE UPDATE ON documents FOR EACH ROW EXECUTE
PROCEDURE update_updated_at_column()
documents_count BEFORE INSERT OR DELETE ON documents FOR EACH ROW
EXECUTE PROCEDURE count_trig()
folder_document_count_trig BEFORE INSERT OR DELETE OR UPDATE ON
documents FOR EACH ROW EXECUTE PROCEDURE update_folder_count()
tags_in_trash_document_count_trig BEFORE DELETE OR UPDATE ON documents
FOR EACH ROW EXECUTE PROCEDURE update_tag_trash_count()

Table/Index Sizes
-----------------

Current size:
6841 MB | pg_toast_17426
2486 MB | document_search_ix
2172 MB | documents
188 MB | pg_toast_17426_index
113 MB | document_user_id_recvd_ix
76 MB | documents_pkey

Size after building on a new machine from pg_dump:
5564 MB | pg_toast_1599236
1882 MB | documents
1666 MB | document_search_ix
73 MB | pg_toast_1599236_index
40 MB | document_user_id_recvd_ix

Things to know about the table/DB:
----------------------------------
- We currently inserting ~ 5000-10000 documents a day
- We extract text from the documents and store it in the contents field for
full text search
- In the last few months we've added a feature that allows users to update
columns (date, amount, etc), so we're seeing a lot more updates to
the table than before
- 2 massive updates were done to the table in the last few months in which
a particular column was updated for each row in the table
- We're running a pg_dump every hour which takes around 10 min.

What I've tried
---------------

Logging checkpoints: The slow queries happen even in between checkpoints

Logging locks: There are no logs indicating that the slow query is the
result of a lock

Explain plan: Nothing strange, updates are using documents_pkey index

Trying another machine: I switched over to our replica on another box and
was still seeing slow queries

Doing backups less frequently: Slow queries occur even when backup is not
running

Rebuilding document_search_ix index: The index rebuild reduced the index
size from about 4500MB to 1500MB. This didn't appear to reduce the slow
queries
and the size is now at ~ 2400MB after
less than a week

Running vacuum analyze after rebuilding index: Didn't appear to help

Matching iotop output to slow query output: INSERTs are reading a lot of
data, 22MB in this case, but I don't know how to utilize this information.

14:23:03 22739 be/4 postgres 702.11 K/s 66.87 K/s 0.00 % 25.55 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:04 22739 be/4 postgres 2.48 M/s 96.51 K/s 0.00 % 96.33 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:05 22739 be/4 postgres 1221.82 K/s 43.77 K/s 0.00 % 53.84 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:06 22739 be/4 postgres 1242.40 K/s 94.73 K/s 0.00 % 51.53 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:07 22739 be/4 postgres 1376.88 K/s 46.15 K/s 0.00 % 59.85 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:08 22739 be/4 postgres 563.74 K/s 37.09 K/s 0.00 % 29.03 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:09 22739 be/4 postgres 1267.57 K/s 81.54 K/s 0.00 % 47.95 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:10 22739 be/4 postgres 1080.95 K/s 59.43 K/s 0.00 % 48.21 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:11 22739 be/4 postgres 1041.17 K/s 125.98 K/s 0.00 % 49.86 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:13 22739 be/4 postgres 1019.91 K/s 138.55 K/s 0.00 % 42.42 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:14 22739 be/4 postgres 856.88 K/s 103.86 K/s 0.00 % 31.88 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:15 22739 be/4 postgres 1284.18 K/s 170.73 K/s 0.00 % 52.36 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:16 22739 be/4 postgres 1188.97 K/s 74.31 K/s 0.00 % 51.59 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:17 22739 be/4 postgres 1088.19 K/s 111.42 K/s 0.00 % 44.45 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:18 22739 be/4 postgres 1261.87 K/s 133.61 K/s 0.00 % 49.08 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:19 22739 be/4 postgres 1203.82 K/s 137.58 K/s 0.00 % 52.22 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:20 22739 be/4 postgres 1399.45 K/s 133.63 K/s 0.00 % 45.76 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:21 22739 be/4 postgres 1380.05 K/s 126.13 K/s 0.00 % 57.53 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT
14:23:22 22739 be/4 postgres 1236.00 K/s 148.47 K/s 0.00 % 53.78 %
postgres: ourusername ourdb 192.x.x.x(51168) INSERT

What I haven't tried
--------------------
- more aggressive auto-vacuum
- trying gist table for full text search index instead of gin
- removing full text search altogether (are users don't use it very much)
- rebuilding the production table
- vacuum full

Any help on what the issue might be or how to debug further would be
amazing. I'd like to understand this issue better,
both for my business as well as for my own understanding of databases.

Dave Stibrany

Responses

Browse pgsql-performance by date

  From Date Subject
Next Message ktm@rice.edu 2015-09-17 20:12:51 Re: Occasional Really Slow Running Updates/Inserts
Previous Message Eildert Groeneveld 2015-09-17 14:41:08 Re: degrading inser performance