Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.80) (envelope-from ) id 1XxmaP-0000Vh-4n for pgsql-sql@arkaria.postgresql.org; Mon, 08 Dec 2014 00:54:01 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.80) (envelope-from ) id 1XxmaO-0004nh-KD for pgsql-sql@arkaria.postgresql.org; Mon, 08 Dec 2014 00:54:00 +0000 Received: from makus.postgresql.org ([2001:4800:1501:1::229]) by malur.postgresql.org with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1XxmaM-0004k5-HF for pgsql-sql@postgresql.org; Mon, 08 Dec 2014 00:53:58 +0000 Received: from out3-smtp.messagingengine.com ([66.111.4.27]) by makus.postgresql.org with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) (envelope-from ) id 1XxmaI-0000V4-UZ for pgsql-sql@postgresql.org; Mon, 08 Dec 2014 00:53:56 +0000 Received: from compute5.internal (compute5.nyi.internal [10.202.2.45]) by mailout.nyi.internal (Postfix) with ESMTP id 616F72067F for ; Sun, 7 Dec 2014 19:53:53 -0500 (EST) Received: from frontend2 ([10.202.2.161]) by compute5.internal (MEProxy); Sun, 07 Dec 2014 19:53:53 -0500 DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d=aklaver.com; h= x-sasl-enc:message-id:date:from:mime-version:to:subject :references:in-reply-to:content-type:content-transfer-encoding; s=mesmtp; bh=DO8SBpbUlAwvD5Ggvc/dtRDZWiw=; b=iVs1DZ/9M3aLWLzewb gCDJrfMUxWRyv/CT5C3YJKim5Xr0i2nRlINdIEUjTzzbCLesTawSWsXMf06vBlJ7 L/wxzJdhKB7WKvcHf0vvlAyUd4u1v9/mllfOhfk+ZyF4JVxBDPP10ibMW9SGCdlQ ogooZ2EJSQlA9DvvrqJFV2jUY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed/relaxed; d= messagingengine.com; h=x-sasl-enc:message-id:date:from :mime-version:to:subject:references:in-reply-to:content-type :content-transfer-encoding; s=smtpout; bh=DO8SBpbUlAwvD5Ggvc/dtR DZWiw=; b=VjlU5BJOGT8uZW3ARpDDU+ZWeYOzbkxJNVJFPEu0n1h3gQIPxMuX8A dGwPlpLv4JErGdU6En5DVtseK6WzY6/2sTHmvBwdBW617A3HwYXJBVVmTHFuSl5p EhJpeB1TQyI6fTgzgtyewKUqhFPFEXxuFOkLNL4nmLh07e9H/G7Nk= X-Sasl-enc: 8rDMZl3zUYLHpAKPP/k3DzcYetNjDWcZyFPc51v0AzRL 1418000033 Received: from [192.168.1.4] (unknown [174.21.228.172]) by mail.messagingengine.com (Postfix) with ESMTPA id D34796800C3; Sun, 7 Dec 2014 19:53:52 -0500 (EST) Message-ID: <5484F69F.2030006@aklaver.com> Date: Sun, 07 Dec 2014 16:53:51 -0800 From: Adrian Klaver User-Agent: Mozilla/5.0 (X11; Linux i686; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: Tim Dudgeon , pgsql-sql@postgresql.org Subject: Re: querying with index on jsonb slower than standard column. Why? References: <5484DBDA.6090405@gmail.com> <5484EEA7.1030403@aklaver.com> <5484F437.2080402@gmail.com> In-Reply-To: <5484F437.2080402@gmail.com> Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-Pg-Spam-Score: -2.7 (--) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-sql Precedence: bulk Sender: pgsql-sql-owner@postgresql.org On 12/07/2014 04:43 PM, Tim Dudgeon wrote: > > On 07/12/2014 21:19, Adrian Klaver wrote: >> On 12/07/2014 02:59 PM, Tim Dudgeon wrote: >>> I was doing some performance profiling regarding querying against jsonb >>> columns and found something I can't explain. >>> I created json version and standard column versions of some data, and >>> indexed the json 'fields' and the normal columns and executed equivalent >>> queries against both. >>> I find that the json version is quite a bit (approx 3x) slower which I >>> can't explain as both should (and are according to plans are) working >>> against what I would expect are equivalent indexes. >>> >>> Can anyone explain this? >> >> The docs can: >> >> http://www.postgresql.org/docs/9.4/interactive/datatype-json.html#JSON-INDEXING >> > > If so them I'm missing it. > The index created is not a gin index. Its a standard btree index on the > data extracted from the json. So the indexes on the standard columns and > the ones on the 'fields' extracted from the json seem to be equivalent. > But perform differently. Down into the section there is this: "jsonb also supports btree and hash indexes. These are usually useful only if it's important to check equality of complete JSON documents. The btree ordering for jsonb datums is seldom of great interest, but for completeness it is: Object > Array > Boolean > Number > String > Null Object with n pairs > object with n - 1 pairs Array with n elements > array with n - 1 elements Objects with equal numbers of pairs are compared in the order: key-1, value-1, key-2 ... Note that object keys are compared in their storage order; in particular, since shorter keys are stored before longer keys, this can lead to results that might be unintuitive, such as: { "aa": 1, "c": 1} > {"b": 1, "d": 1} Similarly, arrays with equal numbers of elements are compared in the order: element-1, element-2 ... Primitive JSON values are compared using the same comparison rules as for the underlying PostgreSQL data type. Strings are compared using the default database collation. " As I understand it to get useful indexing into the jsonb datum(document) you need to use the GIN indexes. > > Tim >> >>> >>> Example code is here: >>> >>> >>> create table json_test ( >>> id SERIAL, >>> assay1_ic50 FLOAT, >>> assay2_ic50 FLOAT, >>> data JSONB >>> ); >>> >>> DO >>> $do$ >>> DECLARE >>> val1 FLOAT; >>> val2 FLOAT; >>> BEGIN >>> for i in 1..10000000 LOOP >>> val1 = random() * 100; >>> val2 = random() * 100; >>> INSERT INTO json_test (assay1_ic50, assay2_ic50, data) VALUES >>> (val1, val2, ('{"assay1_ic50": ' || val1 || ', "assay2_ic50": ' || >>> val2 || ', "mod": "="}')::jsonb); >>> end LOOP; >>> END >>> $do$ >>> >>> create index idx_data_json_assay1_ic50 on json_test (((data ->> >>> 'assay1_ic50')::float)); >>> create index idx_data_json_assay2_ic50 on json_test (((data ->> >>> 'assay2_ic50')::float)); >>> >>> create index idx_data_col_assay1_ic50 on json_test (assay1_ic50); >>> create index idx_data_col_assay2_ic50 on json_test (assay2_ic50); >>> >>> select count(*) from json_test; >>> select * from json_test limit 10; >>> >>> select count(*) from json_test where (data->>'assay1_ic50')::float > 90 >>> and (data->>'assay2_ic50')::float < 10; >>> select count(*) from json_test where assay1_ic50 > 90 and assay2_ic50 >>> < 10; >>> >>> >>> >>> Thanks >>> Tim >>> >>> >>> >> >> > > > -- Adrian Klaver adrian.klaver@aklaver.com -- Sent via pgsql-sql mailing list (pgsql-sql@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-sql