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 1grWlg-0002WI-Tk for pgsql-hackers@arkaria.postgresql.org; Wed, 06 Feb 2019 23:38:13 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1grWlf-0001bK-7L for pgsql-hackers@arkaria.postgresql.org; Wed, 06 Feb 2019 23:38:11 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1grWle-0001bD-Rf for pgsql-hackers@lists.postgresql.org; Wed, 06 Feb 2019 23:38:11 +0000 Received: from mail-wr1-x433.google.com ([2a00:1450:4864:20::433]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1grWlb-0005XA-Pe for pgsql-hackers@lists.postgresql.org; Wed, 06 Feb 2019 23:38:10 +0000 Received: by mail-wr1-x433.google.com with SMTP id c8so2728011wrs.4 for ; Wed, 06 Feb 2019 15:38:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=2ndquadrant-com.20150623.gappssmtp.com; s=20150623; h=to:from:subject:message-id:date:user-agent:mime-version :content-language; bh=6Bd/nwVqLSerTQFIEKuo5gwMJ2duDfdMlBVggPurT58=; b=e97TzOcqltQBlJmiaw1s/QBrsw5w1Tcbv3oDGbaFRgsJhQrAeOQvUr7tg8Q/jz6XVi pR8ShdxTwbkOhUPPSZrPOfwm7FjoXX//YtSpi3nPpdAhCGDAAvg1oNO0zXSZtgBHIVJX WfjZbMZ11RWVkauVDCpVZjCQhUVRFZb8YaQCFbxxhKePWZiGGFWsYPtYWRerD738lnC/ NvrnpaDrV+9KKEn75fVcyJTMVq3zqmpAA9V8H6PTMxOAGeL/oHGRSyPzuL5QhX5cwM55 /ixyH7cOLLp2YbO7iFcCGEVmRAj2QavENZ1xOIViKWef90sRLWrdaa6KRm7jg8vNot9v Ozag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:to:from:subject:message-id:date:user-agent :mime-version:content-language; bh=6Bd/nwVqLSerTQFIEKuo5gwMJ2duDfdMlBVggPurT58=; b=QfJGrrWX1jNEGM3E+e5ucAoffea2vTfUSl5yT6uP6lD2MXpDEdll63tN3DBg6dEOuV jM7zEtUVcVxmyV4WApTLxjX0fwQ2lBPZ3aQvk8PyQoDHiXRAi4Z0BHH4hiDznbAoBUol 72zbICBx+4P1QkiqqHirAZ5MdLQyHPMqz9nfWFBe35glHQw19n3uBCMHQ2oAv3phI3DU inkWO1BCUEUTAxeXbByNxYPmtOe11SRyvfGrOvqPXoY5nbBBexqNymeCtfbDeZ3briln 0ClzHZxh9ozQI/t7bNb+bRlywyEzfKKt0nzA4+GAfcDml5dG6f3Bpm9Z9Ps7GKdksqSP xFQw== X-Gm-Message-State: AHQUAubrtmwLk+73sRfFT61ZH78SdQ4YyP40aeql1RE6Cxrto6DYXaSr nVQRpHGC4KCLiXuHVaYJoG/LxWPXitRZzmXkq+x8eIhZ06+YvXEN4kZa4bPmGv1K+uhnqjr7TK4 6+gaBzatGa97lvmM1d04bSTXciDR4WQlYx9XoxELY+wrYksbDIsYBdlP5H+IKOyKS+a35FGr0ez kyMtBZjogYi2LdFfcDT6c= X-Google-Smtp-Source: AHgI3IapdmQ3wN7nnChhV8vSJ18hoHw1qSG/A5b8CyYSk9VwV4rompvd1S83HdwT7Viwc2iP850LSQ== X-Received: by 2002:adf:f9cb:: with SMTP id w11mr9593489wrr.201.1549496285184; Wed, 06 Feb 2019 15:38:05 -0800 (PST) Received: from [10.137.2.19] (ip-86-49-245-195.net.upcbroadband.cz. [86.49.245.195]) by smtp.gmail.com with ESMTPSA id k23sm15056807wmj.32.2019.02.06.15.38.04 for (version=TLS1_3 cipher=AEAD-AES128-GCM-SHA256 bits=128/128); Wed, 06 Feb 2019 15:38:04 -0800 (PST) To: Postgres hackers From: Tomas Vondra Subject: performance issue in remove_from_unowned_list() Message-ID: <80c27103-99e4-1d0c-642c-d9f3b94aaa0a@2ndquadrant.com> Date: Thu, 7 Feb 2019 00:38:02 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.4.0 MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="------------9F871583A247B57A036916F9" Content-Language: en-US List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk This is a multi-part message in MIME format. --------------9F871583A247B57A036916F9 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Hi, While working on benchmarks for the syscache patch (negative entries and all of that), I've ran into a an issue in remove_from_unowned_list. If you create a lot of relations in a single transaction (say, 100k) and then abort the transaction (or if it fails for some reason, e.g. because of hitting max_locks_per_transaction), smgrDoPendingDeletes ought to clean relation files. Unfortunately, the constructed srels array is ordered in exactly the opposite way compared to "unowned list" (used by smgrclose). So what happens is that we start with the first relation, walk the whole list unowned list and remove the last item. Then we get the second rel and again walk the whole unowned list until the last item. And so on. For large number of objects that's pretty significant. With 100k rels I've lost the patience after a couple of minutes, and just nuked the whole cluster (interrupting ROLLBACK is a no go, and after a kill the recovery just starts chewing on it again). Of course, transactions creating 100k tables in a single transaction are not that common, but it's not unheard of either (such applications exist, are discussed in the syscache thread, and restoring them from a pg_dump is likely to hit this issue). And the same issue applies to cases that drop a bunch of tables in a single transaction (and I've seen plenty of scripts doing that, although in smaller batches). But it's a bit funnier, because there's also DropRelationFiles() which does smgrclose on a batch of relations too, and it says this /* * Call smgrclose() in reverse order as when smgropen() is called. * This trick enables remove_from_unowned_list() in smgrclose() * to search the SMgrRelation from the unowned list, * with O(1) performance. */ for (i = ndelrels - 1; i >= 0; i--) ... but it's called from two places in xact.c only. And if you trigger the issue with 100k x CREATE TABLE + ROLLBACK, and then force a recovery by killing postmaster, you actually get the very same behavior with always traversing the unowned list for some reason. I'm not quite sure why, but it seems the optimization is exactly the wrong thing to do here. Attached is a WIP patch removing the optimization from DropRelationFiles and adding it to smgrDoPendingDeletes. This resolves the issue, at least in the cases I've been able to reproduce. But maybe we should deal with this issue earlier by ensuring the two lists are ordered the same way from the very beginning, somehow. regards -- Tomas Vondra http://www.2ndQuadrant.com PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services --------------9F871583A247B57A036916F9 Content-Type: text/x-patch; name="smgr-fix.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="smgr-fix.patch" diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c index 0302507e6f..8dc9050343 100644 --- a/src/backend/catalog/storage.c +++ b/src/backend/catalog/storage.c @@ -360,7 +360,13 @@ smgrDoPendingDeletes(bool isCommit) { smgrdounlinkall(srels, nrels, false); - for (i = 0; i < nrels; i++) + /* + * Call smgrclose() in reverse order as when smgropen() is called. + * This trick enables remove_from_unowned_list() in smgrclose() + * to search the SMgrRelation from the unowned list, + * with O(1) performance. + */ + for (i = nrels-1; i >= 0; i--) smgrclose(srels[i]); pfree(srels); diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 2aba2dfe91..6ed68185ed 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -1699,13 +1699,7 @@ DropRelationFiles(RelFileNode *delrels, int ndelrels, bool isRedo) smgrdounlinkall(srels, ndelrels, isRedo); - /* - * Call smgrclose() in reverse order as when smgropen() is called. - * This trick enables remove_from_unowned_list() in smgrclose() - * to search the SMgrRelation from the unowned list, - * with O(1) performance. - */ - for (i = ndelrels - 1; i >= 0; i--) + for (i = 0; i < ndelrels; i++) smgrclose(srels[i]); pfree(srels); } --------------9F871583A247B57A036916F9--