Was this page helpful?
Caution
You're viewing documentation for an unstable version of ScyllaDB Manual. Switch to the latest stable version.
Pattern Search in ScyllaDB¶
What Is Pattern Search¶
Pattern Search finds the rows whose text column matches a LIKE
pattern, such as '%abc%', 'abc%' or 'a%b', but served by an
index rather than by a scan of the table. The index node does not match
approximately: a value matches when the whole of it matches the pattern. The
pattern has the same syntax as in a filtered LIKE, with the
same %, _ and \ rules, but the query does not behave like a filtered
one in other respects; see
Indexed vs. Filtered LIKE.
It suits values that are searched by any part of them rather than by whole words, such as product codes, identifiers and tags. For example, with the table below:
code
------------
AB-1024-XL
AB-2048-S
ab-4096-M
XAB-1024
CD-1024-AB
code LIKE 'AB-%'returns AB-1024-XL and AB-2048-S, and also ab-4096-M on an index created with'case_sensitive': 'false'. It does not return XAB-1024 or CD-1024-AB, which containABbut do not start withAB-.code LIKE '%024%'returns AB-1024-XL, XAB-1024 and CD-1024-AB. It matches inside1024, which a word-based search would not find.code LIKE '%-_'returns AB-2048-S and ab-4096-M, the codes that end with a one-character suffix.
A row either matches the pattern or it does not, and no row is ranked above
another: CD-1024-AB, with AB at its end, is as much a result of
code LIKE '%AB%' as AB-1024-XL. When more rows match than the LIMIT,
which of them are returned is not specified. A query can also return fewer rows
than its LIMIT, even when more rows match, if a row was deleted after the
index found it.
Pattern Search does not tokenize, stem or rank. For word-based search ranked by relevance, use Full-Text Search.
Creating a Pattern Index¶
A pattern_index on a column serves the LIKE restrictions on that
column. Such a query does not need ALLOW FILTERING; if it is given, it is
ignored and the index is still used. To create the index:
CREATE CUSTOM INDEX ON ks.parts (code) USING 'pattern_index';
or, to match regardless of letter case:
CREATE CUSTOM INDEX ON ks.parts (code) USING 'pattern_index'
WITH OPTIONS = {'case_sensitive': 'false'};
For the option and its default, see Pattern Index.
Warning
Creating a pattern index changes the meaning of every LIKE on its
column, for every application that queries the column. Once the index
exists, a LIKE on the column is served by the index, even with
ALLOW FILTERING:
Queries that worked by filtering start failing. The
LIKEmust be the only restriction in theWHEREclause, and the query needs aLIMITof at most 1000, so for example aLIKEtogether with a restriction on the partition key, or aLIKEwithout aLIMIT, is rejected.Queries that still succeed can return different rows, without any error. The index is eventually consistent, so a recent write may be missed, and the rows are neither paged nor ordered. With
'case_sensitive': 'false', matching ignores letter case, so aLIKEreturns rows that a filteredLIKEdoes not.When the index node is unavailable, every
LIKEon the column fails.
CREATE INDEX returns a warning that summarizes these changes. Dropping the
index restores filtered LIKE (see Dropping a Pattern Index). For all
the differences, see
Indexed vs. Filtered LIKE.
Requirements:
The indexed column must be of type
text,varchar, orascii.The indexed column must be a regular column. Primary-key and static columns cannot be indexed.
The table must use tablets (not vnodes).
CDC must be enabled on the table with a TTL of at least 86400 seconds (24 hours) and either
delta = 'full'or postimage enabled, because the index is updated from the CDC log. CDC is enabled automatically when creating a pattern index, so you do not need to configure it manually.
Cell-level TTL, set with the standard USING TTL syntax on INSERT or
UPDATE, makes the value unreadable at its expiration deadline but does not
generate a CDC event, so the pattern index is not updated and keeps a stale
entry for that value. A LIKE query can then still return the row, with the
expired value read as null. If the index must reflect expiration, use the
Per-row TTL feature instead.
Querying with LIKE¶
On a column with a pattern index, LIKE queries look like this:
SELECT id, code FROM ks.parts
WHERE code LIKE '%024%'
LIMIT 10;
SELECT id, code FROM ks.parts
WHERE code LIKE 'AB-%'
LIMIT 10;
SELECT id, code FROM ks.parts
WHERE code LIKE ?
LIMIT 10;
Creating the index is a deliberate choice to serve every LIKE on the
column from the index, even with ALLOW FILTERING. The full rules are in
Indexed LIKE queries.
Indexed vs. Filtered LIKE¶
Without a pattern index, LIKE is a filter: ScyllaDB reads the rows and
checks each value against the pattern, as described in
LIKE Operator. On a column with a pattern index, the
same LIKE is served by the index instead, and the query differs from a
filtered one as follows:
Filtered |
Indexed |
|
|---|---|---|
Where it works |
Every deployment, on any |
ScyllaDB Cloud, on a regular column with a
|
Matching |
Always case-sensitive. |
Case-sensitive, unless the index was created with
|
Patterns |
Any pattern. |
The same syntax. Which patterns are supported depends on the index node. |
|
Required. |
Not needed. If given, it is ignored and the index is still used. |
|
Optional, any value. |
Required, at most 1000. |
Other restrictions and clauses |
Allowed, as in any query with
|
None: the |
Paging |
Paged like any other query. |
Not paged: the whole result is returned in one page,
with a warning when the page size is smaller than
|
Order |
The order of a scan: by token, then by clustering key. |
Not specified. When more rows match than the
|
Consistency |
The rows are read, and matched, at the query’s consistency level. |
Eventually consistent, and the rows are not checked against the pattern again: shortly after a write, a query may miss a new value, or return a row whose current value no longer matches the pattern. |
Failure |
Fails as any read does. |
Also fails when the index node is unavailable or does not support the pattern. |
Dropping a Pattern Index¶
Dropping the index restores filtered LIKE on its column:
DROP INDEX ks.parts_code_idx;
From then on, a LIKE on the column is a filter again: it requires
ALLOW FILTERING, matches case-sensitively, and follows the rules of
LIKE Operator. Dropping the index is the way back when
the indexed LIKE does not suit an application that queries the column.