Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eNNDS-0006nN-9K for pgsql-performance@arkaria.postgresql.org; Fri, 08 Dec 2017 18:17:42 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eNNDR-0006ne-6U for pgsql-performance@arkaria.postgresql.org; Fri, 08 Dec 2017 18:17:41 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1eNNDQ-0006nU-Sg for pgsql-performance@lists.postgresql.org; Fri, 08 Dec 2017 18:17:41 +0000 Received: from out3-smtp.messagingengine.com ([66.111.4.27]) by makus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA384:256) (Exim 4.89) (envelope-from ) id 1eNNDN-0008Ls-Ik for pgsql-performance@postgresql.org; Fri, 08 Dec 2017 18:17:39 +0000 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id F281A20D56; Fri, 8 Dec 2017 13:17:35 -0500 (EST) Received: from frontend1 ([10.202.2.160]) by compute5.internal (MEProxy); Fri, 08 Dec 2017 13:17:35 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:content-transfer-encoding:content-type :date:from:in-reply-to:message-id:mime-version:references :subject:to:x-me-sender:x-me-sender:x-sasl-enc; s=fm1; bh=0yFABq FX0hg7TJw6CdFRoDtDamDdPMO/DHQ57YlYG5A=; b=CZiUUrULsQe8X20AriNCC3 E6KMQfhU3J2mqnAXmR2WBaAEsphhVo1IwmZxtCbsFIMKawmn0Rx/B+2Uf/rgzL8U yXQcz3akazQI7OpRkiLmxPso5GbPfL8TlOUYzm9f+4/5Wg0nPx+c7T8XV1q1sXNL 514hkontfxc/Ep9P9gDrO89xrnzmN1UumcAtPj+eW1dt9p7FgN0Nvo7ok+c+Y+r3 bscnPwI1cTINVowc4b/lwgtKbuAXQjVIuZJjfTplDfQZOpArvVRix0xzrU9S5Aod obAJ5EfJTtCHUZbYp7VXix8CaVYed+OwLUVUQ5REMDov0hBMa9oWtGwvjjbmV+IQ == X-ME-Sender: Received: from intern.anarazel.de (unknown [136.24.76.189]) by mail.messagingengine.com (Postfix) with ESMTPA id A15A07FAC9; Fri, 8 Dec 2017 13:17:35 -0500 (EST) Date: Fri, 8 Dec 2017 10:17:34 -0800 From: Andres Freund To: Alex Tokarev Cc: pgsql-performance@postgresql.org Subject: Re: Table with large number of int columns, very slow COPY FROM Message-ID: <20171208181734.db7gk22mtq7i44ax@alap3.anarazel.de> References: MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk Hi, On 2017-12-07 20:21:45 -0800, Alex Tokarev wrote: > I have a set of tables with fairly large number of columns, mostly int with > a few bigints and short char/varchar columns. Išve noticed that Postgres is > pretty slow at inserting data in such a table. I tried to tune every > possible setting: using unlogged tables, increased shared_buffers, etc; even > placed the db cluster on ramfs and turned fsync off. The results are pretty > much the same with the exception of using unlogged tables that improves > performance just a little bit. > I have made a minimally reproducible test case consisting of a table with > 848 columns, inserting partial dataset of 100,000 rows with 240 columns. On > my dev VM the COPY FROM operation takes just shy of 3 seconds to complete, > which is entirely unexpected for such a small dataset. I don't find this to be this absurdly slow. On my laptop loading with a development checkout this takes 1223.950 ms. This is 20mio fields parsed/sec, rows with 69mio fields/sec inserted. Removing the TRUNCATE and running the COPYs concurrently scales well to a few clients, and only stops because my laptop's SSD stops being able to keep up. That said, I do think there's a few places that could stand some improvement. Locally the profile shows up as: + 15.38% postgres libc-2.25.so [.] __GI_____strtoll_l_internal + 11.79% postgres postgres [.] heap_fill_tuple + 8.00% postgres postgres [.] CopyFrom + 7.40% postgres postgres [.] CopyReadLine + 6.79% postgres postgres [.] ExecConstraints + 6.68% postgres postgres [.] NextCopyFromRawFields + 6.36% postgres postgres [.] heap_compute_data_size + 6.02% postgres postgres [.] pg_atoi the strtoll is libc functionality triggered by pg_atoi(), something I've seen show up in numerous profiles. I think it's probably time to have our own optimized version of it rather than relying on libcs. That heap_fill_tuple(), which basically builds a tuple from the parsed datums, takes time somewhat proportional to the number of columns in the table seems hard to avoid, especially because this isn't something we want to optimize for with the price of making more common workloads with fewer columns slower. But there seems quite some micro-optimization potential. That ExecConstraints() shows up seems unsurprising, it has to walk through all the table's columns checking for constraints. We could easily optimize this so we have a separate datastructure listing constraints, but that'd be slower in the very common case of more reasonable numbers of columns. The copy implementation deserves some optimization too... > Herešs a tarball with test schema and data: > http://nohuhu.org/copy_perf.tar.bz2; itšs 338k compressed but expands to > ~50mb. Herešs the result of profiling session with perf: > https://pastebin.com/pjv7JqxD Thanks! Greetings, Andres Freund