Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bB2zh-000699-Oc for pgsql-performance@arkaria.postgresql.org; Thu, 09 Jun 2016 16:39:45 +0000 Received: from localhost ([127.0.0.1] helo=postgresql.org) by malur.postgresql.org with smtp (Exim 4.84_2) (envelope-from ) id 1bB2zh-00005X-7v for pgsql-performance@arkaria.postgresql.org; Thu, 09 Jun 2016 16:39:45 +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_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1bB2y2-0006hX-0l for pgsql-performance@postgresql.org; Thu, 09 Jun 2016 16:38:02 +0000 Received: from mail-vk0-x234.google.com ([2607:f8b0:400c:c05::234]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.84_2) (envelope-from ) id 1bB2xt-00042j-PU for pgsql-performance@postgresql.org; Thu, 09 Jun 2016 16:38:00 +0000 Received: by mail-vk0-x234.google.com with SMTP id d127so62698238vkh.2 for ; Thu, 09 Jun 2016 09:37:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc; bh=f3lcYAcJPzS4QIrWzY7KCKsmJ7gRZzfIv53aE8G3o/Q=; b=Eq0RS4JqxsRt3L4ASOfyizw+2XEBkEbj0J9hMDTvT0PSF2vBtHRKE4ArdImvOtT0CB bH7hcew2XCdAq71Vm1Ub4000tpsvpw/Ylkwz+/KfNSOG5GSg59PNsIpTJYXiKEB0q844 bqjblPVY1pUBzqbzMMkoiaLNfa/rCSoTRoHV4BuTBhmY5TsTGqWEhP4Iu/I8bYrYDQUX InZLDcb28oVCxHb9pXffbmsTp8V/xkKfeBtf8cM8V2surr8GKX4kLL5+JO7AUjx8j1VB LholP+Q6JbwZVIX90j986rvAo0sxMm1/JwxVxhzYX0Emgw+GEnZCRH+k1b18+qlFJF5U y3Yg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to:cc; bh=f3lcYAcJPzS4QIrWzY7KCKsmJ7gRZzfIv53aE8G3o/Q=; b=JBeMruT1xTipCZsd+ibKr31k8EBzhGODgkeUMR0EfOjUOXLXmUPeDREuFXTsI+MPCz +zlm4+MHOsG8Yrtvc3ZAD1j17RGeDy7P61PRycL/1xJvk0nSi/gd1PqrO2IjfqLdcRLa chDKQgEKzrNLFIyGUSnQi4KX3hK+0fduX3K+NrgfwWj6gK8Y4GAU9ORil6AY5aD4ABPI cNY45cmgZDysbg4wir+seXG1+SyjIxN8rYS/QuiJbjsCILnY4nuT3/PSfOqfXAEBu2Ry RPudTDxhMYYTQozzV1ZCrsWi/njiYUplAnPXU/+5AIumr3FovRsJINqmDaNIqT3Qu0NT SvDQ== X-Gm-Message-State: ALyK8tIrrbBj/cNEOEPIZ/77Tn/ehAfUTCdNdv6H54iM3ddLjFe9Jyu4A2rRkVFlPQKk68AQcCeQyK1AByXRvA== X-Received: by 10.176.0.145 with SMTP id 17mr4734492uaj.103.1465490271130; Thu, 09 Jun 2016 09:37:51 -0700 (PDT) MIME-Version: 1.0 Received: by 10.103.131.204 with HTTP; Thu, 9 Jun 2016 09:37:50 -0700 (PDT) In-Reply-To: References: From: Jeff Janes Date: Thu, 9 Jun 2016 09:37:50 -0700 Message-ID: Subject: Re: Performance of LIKE/NOT LIKE when used in single query To: Ed Felstein Cc: "pgsql-performance@postgresql.org" Content-Type: text/plain; charset=UTF-8 X-Pg-Spam-Score: -2.7 (--) List-Archive: List-Help: List-ID: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: X-Mailing-List: pgsql-performance Precedence: bulk Sender: pgsql-performance-owner@postgresql.org On Tue, Jun 7, 2016 at 9:57 PM, Ed Felstein wrote: > Hello, > First time poster here. Bear with me. > Using PostgreSQL 9.5 > I have a situation where I have a LIKE and a NOT LIKE in the same query to > identify strings in a varchar field. Since I am using wildcards, I have > created a GIN index on the field in question, which makes LIKE '%xxxx%' > searches run very fast. The problem is the NOT LIKE phrases, which (as > would be expected) force a sequential scan. Being that we're talking about > millions of records, this is not desirable. > Here's the question... > Is there a way, using a single query, to emulate the process of running the > LIKE part first, then running the NOT LIKE just on those results? Just do it. In my hands, the planner is smart enough to figure it out for itself. explain analyze select * from stuff where synonym like '%BAT%' and synonym not like '%col not like%' ; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------- Bitmap Heap Scan on stuff (cost=16.10..63.08 rows=13 width=14) (actual time=9.465..10.642 rows=23 loops=1) Recheck Cond: (synonym ~~ '%BAT%'::text) Rows Removed by Index Recheck: 76 Filter: (synonym !~~ '%col not like%'::text) Heap Blocks: exact=57 -> Bitmap Index Scan on integrity_synonym_synonym_idx (cost=0.00..16.10 rows=13 width=0) (actual time=8.847..8.847 rows=99 loops=1) Index Cond: (synonym ~~ '%BAT%'::text) Planning time: 18.261 ms Execution time: 10.932 ms So it is using the index for the positive match, and filtering those results for the negative match, just as you wanted. Cheers, Jeff -- Sent via pgsql-performance mailing list (pgsql-performance@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-performance