האצה של ביטויים להתאמת תבניות

אינדקסים של חיפוש ב-Spanner יכולים להאיץ ביטויים של התאמת תבניות, כמו LIKE,‏ STARTS_WITH,‏ ENDS_WITH ופרדיקט של התאמת ביטויים רגולריים REGEXP_CONTAINS. בדף הזה מוסבר איך ליצור ולהגדיר אינדקס חיפוש באמצעות TOKENIZE_NGRAMS כדי להאיץ את התאמת התבניות.

הגדרת n-gram TOKENLIST להאצת התאמת תבניות

כדי להפעיל האצה של ביטויי התאמה לתבניות, צריך ליצור טוקניזציה של עמודה STRING באותיות קטנות באמצעות TOKENIZE_NGRAMS ולאחסן את העמודה STRING באמצעות פסוקית STORING ב-GoogleSQL או פסוקית INCLUDE ב-PostgreSQL.

GoogleSQL

CREATE TABLE Albums (
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
AlbumTitle_Ngram_Tokens TOKENLIST AS (
  TOKENIZE_NGRAMS(LOWER(AlbumTitle), ngram_size_min=>3, ngram_size_max=>4)) HIDDEN,
) PRIMARY KEY(AlbumId);

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Ngram_Tokens) STORING (AlbumTitle);

PostgreSQL

CREATE TABLE albums (
albumid bigint NOT NULL,
album_title varchar,
album_title_ngrams_tokens spanner.tokenlist GENERATED ALWAYS AS (
  spanner.tokenize_ngrams(
    lower(album_title),
    ngram_size_min => 3,
    ngram_size_max => 4
  )
) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));

CREATE SEARCH INDEX albumsidx ON
albums(album_title_ngrams_tokens) INCLUDE (album_title);

האצה אוטומטית של שאילתות עם פרדיקטים של התאמת תבניות

יכול להיות שאופטימיזציית השאילתות תבחר להאיץ את השאילתות הבאות באמצעות AlbumsIndex עם AlbumTitle_Ngram_Tokens. אפשר גם להוסיף לשאילתה את האפשרות @{force_index = AlbumsIndex} כדי לחייב את כלי האופטימיזציה להשתמש ב-AlbumsIndex.

GoogleSQL

ב-GoogleSQL, אנחנו מאיצים את LIKE,‏ STARTS_WITH,‏ ENDS_WITH ו-REGEXP_CONTAINS.

  • LIKE predicate:

    SELECT AlbumId
    FROM Albums @{FORCE_INDEX=AlbumsIndex}
    WHERE AlbumTitle LIKE "%999%";
    
  • STARTS_WITH predicate:

    SELECT AlbumId
    FROM Albums @{FORCE_INDEX=AlbumsIndex}
    WHERE STARTS_WITH(AlbumTitle, "apple")
    
  • ENDS_WITH predicate:

    SELECT AlbumId
    FROM Albums @{FORCE_INDEX=AlbumsIndex}
    WHERE ENDS_WITH(AlbumTitle, "apple")
    
  • REGEXP_CONTAINS predicate:

    SELECT AlbumId
    FROM Albums @{FORCE_INDEX=AlbumsIndex}
    WHERE REGEXP_CONTAINS(AlbumTitle, r"(good|great)[ ]+morning")
    

PostgreSQL

ב-PostgreSQL, אנחנו מאיצים את LIKE ואת STARTS_WITH.

  • LIKE predicate:

    SELECT albumid
    FROM albums /*@ FORCE_INDEX = albumsidx */
    WHERE album_title like '%999%';
    
  • STARTS_WITH predicate:

    SELECT albumid
    FROM albums /*@ FORCE_INDEX = albumsidx */
    WHERE starts_with(album_title, 'apple')
    

דרישות מוקדמות בנוגע להאצה

כדי ש-Spanner יאפשר את ההאצה הזו, הכללים הבאים צריכים להתקיים:

  • האינדקס צריך לאחסן את העמודה STRING באמצעות פסקה STORING ב-GoogleSQL או פסקה INCLUDE ב-PostgreSQL. הפעולה הזו מונעת הצטרפות חוזרת יקרה לטבלת הבסיס במהלך סינון אחרי שליפה, וזה חשוב מאוד לביצועים כשחיפוש שולף יותר מדי מסמכים.
  • העמודה STRING חייבת להיות מחולקת לטוקנים באמצעות TOKENIZE_NGRAMS.
  • הטוקניזציה צריכה לחול על LOWER(column_name) ולא על column_name.
  • הדפוס LIKE, הקידומת STARTS_WITH, הסיומת ENDS_WITH או הביטוי הרגולרי REGEXP_CONTAINS חייבים להיות מוגדרים כמחרוזת קבועה. כדי להימנע מהאצה בדפוסים קצרים מדי, אין תמיכה בפרמטרים של שאילתות.
  • הדפוס LIKE, הקידומת STARTS_WITH, הסיומת ENDS_WITH או הביטוי הרגולרי REGEXP_CONTAINS צריכים להכיל מספיק טקסט כדי ליצור לפחות n-גרם אחד. לדוגמה, המחרוזת r".*" לא עומדת בדרישות כי אין רצף של תווים שתואם לה. באופן דומה, אם הגודל המינימלי של ה-ngram מוגדר כ-3, הפרדיקט "%ab%" של LIKE לא עומד בדרישות כי "ab" (גודל 2) קצר מדי.

המאמרים הבאים