On Wed, Dec 27, 2017 at 10:13 AM, Jean Baro <jfb...@gmail.com> wrote:
> Hello, > > We are still seeing queries (by UserID + UserCountry) taking over 2 > seconds, even when there is no batch insert going on at the same time. > > Each query returns from 100 to 200 messagens, which would be a 400kb pay > load, which is super tiny. > > I don't know what else I can do with the limitations (m4.large), 167MM > rows, almost 500GB database and 29GB of indexes (all indexes). > > I am probably to optimistic, but I was expecting queries (up to 50 queries > per second) to return (99th) under 500ms or even less, as the index is > simple, there is no aggregation or join involves. > > Any suggestion? > Although you aren't querying by it, if your id column is actually a UUID, as a best practice I strongly recommend switching the column type to uuid. If you do query by the primary key, a uuid query will be much faster than a char or varchar column query. You'll need to submit a more complete explain plan than what you have below. Try using: explain (analyze, costs, verbose, buffers) select ... > The table structure: > CREATE TABLE public.card > ( > id character(36) NOT NULL, > user_id character varying(40) NOT NULL, > user_country character(2) NOT NULL, > user_channel character varying(40), > user_role character varying(40), > created_by_system_key character(36) NOT NULL, > created_by_username character varying(40), > created_at timestamp with time zone NOT NULL, > last_modified_at timestamp with time zone NOT NULL, > date_start timestamp with time zone NOT NULL, > date_end timestamp with time zone NOT NULL, > payload json NOT NULL, > tags character varying(500), > menu character varying(50), > deleted boolean NOT NULL, > campaign character varying(500) NOT NULL, > correlation_id character varying(50), > PRIMARY KEY (id) > ); > > CREATE INDEX idx_user_country > ON public.card USING btree > (user_id COLLATE pg_catalog."default", user_country COLLATE > pg_catalog."default"); > > CREATE INDEX idx_last_modified_at > ON public.card USING btree > (last_modified_at ASC NULLS LAST); > > CREATE INDEX idx_campaign > ON public.card USING btree > (campaign ASC NULLS LAST) > > The EXPLAIN > > 'Index Scan using idx_user_country on card (cost=0.57..1854.66 rows=460 > width=922)' > ' Index Cond: (((user_id)::text = '4684'::text) AND (user_country = > 'BR'::bpchar))' > > > > Em 25 de dez de 2017 01:10, "Jean Baro" <jfb...@gmail.com> escreveu: > >> Thanks for the clarification guys. >> >> It will be super useful. After trying this I'll post the results! >> >> Merry Christmas! >> >> Em 25 de dez de 2017 00:59, "Danylo Hlynskyi" <abcz2.upr...@gmail.com> >> escreveu: >> >>> I had an opportunity to perform insertion of 700MM rows into Aurora >>> Postgresql, for which performance insights are available. Turns out, that >>> there are two stages of insert slowdown - first happens when max WAL >>> buffers limit reached, second happens around 1 hour after. >>> >>> The first stage cuts insert performance twice, and WALWrite lock is main >>> bottleneck. I think WAL just can't sync changes log that fast, so it waits >>> while older log entries are flushed. This creates both read and write IO. >>> >>> The second stage is unique to Aurora/RDS and is characterized by >>> excessive read data locks and total read IO. I couldn't figure out why does >>> it read so much in a write only process, and AWS support didn't answer yet. >>> >>> So, for you, try to throttle inserts so WAL is never overfilled and you >>> don't experience WALWrite locks, and then increase wal buffers to max. >>> >>> 24 груд. 2017 р. 21:51 "Jean Baro" <jfb...@gmail.com> пише: >>> >>> Hi there, >>> >>> We are testing a new application to try to find performance issues. >>> >>> AWS RDS m4.large 500GB storage (SSD) >>> >>> One table only, called Messages: >>> >>> Uuid >>> Country (ISO) >>> Role (Text) >>> User id (Text) >>> GroupId (integer) >>> Channel (text) >>> Title (Text) >>> Payload (JSON, up to 20kb) >>> Starts_in (UTC) >>> Expires_in (UTC) >>> Seen (boolean) >>> Deleted (boolean) >>> LastUpdate (UTC) >>> Created_by (UTC) >>> Created_in (UTC) >>> >>> Indexes: >>> >>> UUID (PK) >>> UserID + Country (main index) >>> LastUpdate >>> GroupID >>> >>> >>> We inserted 160MM rows, around 2KB each. No partitioning. >>> >>> Insert started at around 3.000 inserts per second, but (as expected) >>> started to slow down as the number of rows increased. In the end we got >>> around 500 inserts per second. >>> >>> Queries by Userd_ID + Country took less than 2 seconds, but while the >>> batch insert was running the queries took over 20 seconds!!! >>> >>> We had 20 Lambda getting messages from SQS and bulk inserting them into >>> Postgresql. >>> >>> The insert performance is important, but we would slow it down if needed >>> in order to ensure a more flat query performance. (Below 2 seconds). Each >>> query (userId + country) returns around 100 diferent messages, which are >>> filtered and order by the synchronous Lambda function. So we don't do any >>> special filtering, sorting, ordering or full text search in Postgres. In >>> some ways we use it more like a glorified file system. :) >>> >>> We are going to limit the number of lambda workers to 1 or 2, and then >>> run some queries concurrently to see if the query performance is not affect >>> too much. We aim to get at least 50 queries per second (returning 100 >>> messages each) under 2 seconds, even when there is millions of messages on >>> SQS being inserted into PG. >>> >>> We haven't done any performance tuning in the DB. >>> >>> With all that said, the question is: >>> >>> What can be done to ensure good query performance (UserID+ country) even >>> when the bulk insert is running (low priority). >>> >>> We are limited to use AWS RDS at the moment. >>> >>> Cheers >>> >>> >>> >>>