简体   繁体   中英

sql Like alternate

Is there any other solution available to use instead of Like to match starts with?

here is my query to match starts with using like.

explain analyze select * from completedcalls where call_id like 'GWYA4NvSLzoIcvA7RAtmn_a9IelwOQeH@209.44.103.3%';
                                                    QUERY PLAN                                                    
------------------------------------------------------------------------------------------------------------------
 Seq Scan on completedcalls  (cost=0.00..52659.96 rows=112 width=228) (actual time=1.541..249.857 rows=2 loops=1)
   Filter: ((call_id)::text ~~ 'GWYA4NvSLzoIcvA7RAtmn_a9IelwOQeH@209.44.103.3%'::text)
 Total runtime: 249.893 ms
(3 rows)

which is very expansive because it does sequence scan instead of index scan. due to nature of like it can not use index on provided column. index of column is simple as:

"i_call_id" btree (call_id)

Is there any special class of index which can help like to improve speed, or any other way to achieve same without using like?

Used Table script is:

              Table "public.completedcalls"
    Column     |           Type           |  Modifiers   
---------------+--------------------------+--------------
 call_id       | character varying(128)   | 
 sip_code      | integer                  | 
 duration      | integer                  | 
 setup_time    | timestamp with time zone | not null
 authname      | character varying(30)    | 
 src_sig_ip    | character varying(20)    | 
 dst_sig_ip    | character varying(20)    | 
 cld           | character varying(22)    | 
 cli           | character varying(22)    | 
Indexes:
    "i_call_id" btree (call_id)
    "i_dst_sig_ip" btree (dst_sig_ip)

This case of LIKE index use (or lack thereof) is described in the doc :

In short you should create the index as

create index i_call_id on completedcalls(call_id varchar_pattern_ops);

But read the page linked above for the caveats.

LIKE statements can still be used with b-tree indexes , assuming that there is no leading wildcard:

The optimizer can also use a B-tree index for queries involving the pattern matching operators LIKE and ~ if the pattern is a constant and is anchored to the beginning of the string — for example, col LIKE 'foo%' or col ~ '^foo' , but not col LIKE '%bar' .

If your index isn't being used, then it is for a reason other than the usage of LIKE shown here...

While I'm not sure if it would help the performance, have you looked into using regular expressions? You could use the caret ^ to return the records located at the beginning of the string.

Maybe something like this:

select * 
from completedcalls 
where call_id ~ '^GWYA4NvSLzoIcvA7RAtmn_a9IelwOQeH@209.44.103.3';

LIKE is able to use an index on a condition with a trailing % .

It's possible that the optimizer thinks a full scan would be better than an index scan, as the latter required additional table lookups for other columns and record visibility scope.

From the looks of it, you should probably split up that call_id column into separate columns for each of the components. For example, you could add additional columns with indices for what looks like an ID and an IP address in your example, make those indices and then select on those.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM