Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1gxnpc-0007yo-Bf for pgsql-performance@arkaria.postgresql.org; Sun, 24 Feb 2019 07:04:12 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1gxnpa-000564-LA for pgsql-performance@arkaria.postgresql.org; Sun, 24 Feb 2019 07:04:10 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1gxnpa-00055x-6G for pgsql-performance@lists.postgresql.org; Sun, 24 Feb 2019 07:04:10 +0000 Received: from mail-it1-x12c.google.com ([2607:f8b0:4864:20::12c]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1gxnpS-0007vn-Gf for pgsql-performance@postgresql.org; Sun, 24 Feb 2019 07:04:08 +0000 Received: by mail-it1-x12c.google.com with SMTP id l66so9116623itg.3 for ; Sat, 23 Feb 2019 23:04:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:content-transfer-encoding:in-reply-to :user-agent; bh=cyQIvT1eQsK6lUEPtyEXpswY2xd+DUwjYaCOkQrMexY=; b=beI+R31zsWJNV45qKtRO06z2ZhdnyzVLBD/PmOjJ0sxiChWW4iZvIYX6ugqkVyI1fA TzwBOGwU6UASl8OQrywhXiDMCIASAA9SNmWRX1WKzQ2XF3UihtuHf5c15hDYWA7eWGLR ZK2/BeeD2+eVoQWZikWBpaJXWx19sWhfhir74c9PlSM3duRGtqUM7pdtGuaCu1SdOdka 7f66PWg40ZvStUSZIT8dQZshUoy3zC75QdUIvdPo9p0uUTxl18d/DIg1Dlx9hzpsfe+c HqYNnK9gQ5vn5f1kMqjW4I6qdsWf5yanyojWji6EilYDaHXgWwqOVle2RId3XQF31ur7 wJjQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:content-transfer-encoding :in-reply-to:user-agent; bh=cyQIvT1eQsK6lUEPtyEXpswY2xd+DUwjYaCOkQrMexY=; b=nyZOMKR9XTfDvk+eF02NHCdhEb3/hfoSR0fP5TOloMrrjm0+8YK+j2Re81NaIprkV1 +BfZMxWO1BznXoFFu5tAXNI8Bd9bYMLpfTwWEwVPJas2Y89/ergId7lnHyT49mSPCoj3 502aCHbJUU3wekufYPy+b9oST6n3yFlUxSi3A7VtaW95ouZaxQ1AZPOUpe4UEoLYF/vf 2qHTDzuQq3fGmrYdHfyayBTbk19k/Z/Oe0GFojcVPrHuhk/h98hPoV4eDrb+HrT1wJCH ySoOQRkmUYh4qDKouCAgC2ojOmWt+UHKKZIid+QMJykroVLbPW5W6/WoZne7UfbcyCaf fNAQ== X-Gm-Message-State: AHQUAua+fLvTxGmKIax6sRUHbOMKvGaZw/9A3Fqd/uI+ykZTpUOZZNf0 5aoiaUrBL6OijlENTV3BVR9jng== X-Google-Smtp-Source: AHgI3IbQJDsd4ZB2Piq248gmnDwWeQvWgQjmVn1VGiIJG2VFz3/6jxiWf1woBkKcmhEgYgpeptKS8w== X-Received: by 2002:a02:5ec9:: with SMTP id h192mr6749714jab.141.1550991841223; Sat, 23 Feb 2019 23:04:01 -0800 (PST) Received: from pryzbyj (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id p17sm3131103itp.36.2019.02.23.23.03.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 23 Feb 2019 23:04:00 -0800 (PST) Received: by pryzbyj (Postfix, from userid 1000) id 0D392800997; Sun, 24 Feb 2019 01:03:58 -0600 (CST) Date: Sun, 24 Feb 2019 01:03:58 -0600 From: Justin Pryzby To: Gunther Cc: pgsql-performance@postgresql.org Subject: Re: Massive parallel queue table causes index deterioration, but REINDEX fails with deadlocks. Message-ID: <20190224070358.GJ28750@telsasoft.com> References: <33bae6e3-1c5a-77f0-ee99-408fbf0fbb83@gusw.net> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <33bae6e3-1c5a-77f0-ee99-408fbf0fbb83@gusw.net> User-Agent: Mutt/1.5.23 (2014-03-12) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Some ideas: You could ALTER TABLE SET (fillfactor=50) to try to maximize use of HOT indices during UPDATEs (check pg_stat_user_indexes). You could also ALTER TABLE SET autovacuum parameters for more aggressive vacuuming. You could recreate indices using the CONCURRENTLY trick (CREATE INDEX CONCURRENTLY new; DROP old; ALTER .. RENAME;) On Sat, Feb 23, 2019 at 04:05:51PM -0500, Gunther wrote: > I am using an SQL queue for distributing work to massively parallel workers. > Workers come in servers with 12 parallel threads. One of those worker sets > handles 7 transactions per second. If I add a second one, for 24 parallel > workers, it scales to 14 /s. Even a third, for 36 parallel workers, I can > add to reach 21 /s. If I try a fourth set, 48 workers, I end up in trouble. > But that isn't even so much my problem rather than the fact that in short > time, the performance will deteriorate, and it looks like that is because > the queue index deteriorates and needs a REINDEX. > > The queue table is essentially this: > > CREATE TABLE Queue ( > jobId bigint, > action text, > pending boolean, > result text > ); > > the dequeue operation is essentially this: > > BEGIN > > SELECT jobId, action >   FROM Queue >   WHERE pending > FOR UPDATE SKIP LOCKED > > which is a wonderful concept with the SKIP LOCKED. > > Then I perform the action and finally: > > UPDATE Queue > SET pending = false, > result = ? > WHERE jobId = ? > > COMMIT > > I thought to keep my index tight, I would define it like this: > > CREATE UNIQUE INDEX Queue_idx_pending ON Queue(jobId) WHERE pending; > > so that only pending jobs are in that index. > > When a job is done, follow up work is often inserted into the Queue as > pending, thus adding to that index. > > Below is the performance chart. > > The blue line at the bottom is the db server. > > > You can see the orange line is the first worker server with 12 threads. It > settled into a steady state of 7/s ran with 90% CPU for some 30 min, and > then the database CPU% started climbing and I tried to rebuild the indexes > on the queue, got stuck there, exclusive lock, no jobs were processing, but > the exclusive lock was never obtained for too long. So I shut down the > worker server. Database quiet I could resolve the messed up indexes and > restarted again. Soon I added a second worker server (green line) starting > around 19:15. Once settled in they were pulling 14/s together. but you can > see in just 15 min, the db server CPU % climbed again to over 40% and the > performance of the workers dropped, their load falling to 30%. Now at around > 19:30 I stopped them all, REINDEXed the queue table and then started 3 > workers servers simultaneously. They settled in to 21/s but in just 10 min > again the deterioration happened. Again I stopped them all, REINDEXed, and > now started 4 worker servers (48 threads). This time 5 min was not enough to > see them ever settling into a decent 28/s transaction rate, but I guess they > might have reached that for a minute or two, only for the index > deteriorating again. I did another stop now started only 2 servers and > again, soon the index deteriorated again. > > Clearly that index is deteriorating quickly, in about 10,000 transactions. > > BTW: when I said 7/s, it is in reality about 4 times as many transactions, > because of the follow up jobs that also get added on this queue. So 10,0000 > transactions may be 30 or 40 k transactions before the index deteriorates. > > Do you have any suggestion how I can avoid that index deterioration problem > smoothly? > > I figured I might just pause all workers briefly to schedule the REINDEX > Queue command, but the problem with this is that while the transaction > volume is large, some jobs may take minutes to process, and in that case we > need to wait minutes to quiet the database with then 47 workers sitting as > idle capacity waiting for the 48th to finish so that the index can be > rebuilt! > > Of course I tried to resolve the issue with vacuumdb --analyze (just in case > if the autovacuum doesn't act in time) and that doesn't help. Vacuumdb > --full --analyze would probably help but can't work because it required an > exclusive table lock. > > I tried to just create a new index of the same > > CREATE UNIQUE INDEX Queue_idx2_pending ON Queue(jobId) WHERE pending; > DROP INDEX Queue_idx_pending; > ANALYZE Queue; > > but with that I got completely stuck with two indexes where I could not > remove either of them for those locking issues. And REINDEX will give me a > deadlock error rightout. > > I am looking for a way to manage that index so that it does not deteriorate. > > May be if I was not defining it with > > ... WHERE pending; > > then it would only grow, but never shrink. May be that helps somehow? I > doubt it though. Adding to an index also causes deterioration, and most of > the rows would be irrelevant because they would be past work. It would be > nicer if there was another smooth way.