חיפוש נתונים שנוספו לאינדקס

חיפוש נתונים שנוספו לאינדקס ב-BigQuery מאפשר לשפר את ביצועי השאילתות ולצמצם את כמות הנתונים שנסרקים. אתם יכולים להשתמש בפונקציה SEARCH ובאופרטורים הנתמכים בטבלאות שנוספו לאינדקס כדי לחסוך כמה שיותר בייטים מעובדים ואלפיות שנייה של שימוש ב-slot, במיוחד כשמאחזרים חלק קטן מסך כל השורות.

יצירת אינדקס חיפוש

הטבלה הבאה, שנקראת Logs, משמשת להצגת דרכים שונות לשימוש בפונקציה SEARCH. הטבלה בדוגמה הזו קטנה, אבל בפועל, ככל שהטבלה גדולה יותר, כך השיפור בביצועים באמצעות SEARCH משמעותי יותר.

CREATE TABLE my_dataset.Logs (Level STRING, Source STRING, Message STRING)
AS (
  SELECT 'INFO' as Level, '65.177.8.234' as Source, 'Entry Foo-Bar created' as Message
  UNION ALL
  SELECT 'WARNING', '132.249.240.10', 'Entry Foo-Bar already exists, created by 65.177.8.234'
  UNION ALL
  SELECT 'INFO', '94.60.64.181', 'Entry Foo-Bar deleted'
  UNION ALL
  SELECT 'SEVERE', '4.113.82.10', 'Entry Foo-Bar does not exist, deleted by 94.60.64.181'
  UNION ALL
  SELECT 'INFO', '181.94.60.64', 'Entry Foo-Baz created'
);

הטבלה נראית כך:

+---------+----------------+-------------------------------------------------------+
| Level   | Source         | Message                                               |
+---------+----------------+-------------------------------------------------------+
| INFO    | 65.177.8.234   | Entry Foo-Bar created                                 |
| WARNING | 132.249.240.10 | Entry Foo-Bar already exists, created by 65.177.8.234 |
| INFO    | 94.60.64.181   | Entry Foo-Bar deleted                                 |
| SEVERE  | 4.113.82.10    | Entry Foo-Bar does not exist, deleted by 94.60.64.181 |
| INFO    | 181.94.60.64   | Entry Foo-Baz created                                 |
+---------+----------------+-------------------------------------------------------+

יוצרים אינדקס חיפוש בטבלה Logs באמצעות מנתח הטקסט שמוגדר כברירת מחדל:

CREATE SEARCH INDEX my_index ON my_dataset.Logs(ALL COLUMNS);

מידע נוסף על אינדקס החיפוש, ראה ניהול אינדקס החיפוש.

שימוש בפונקציה SEARCH

הפונקציה SEARCH מאפשרת חיפוש של נתונים באמצעות אסימונים. כדי לבצע אופטימיזציה של החיפושים, מומלץ להשתמש ב-SEARCH עם אינדקס. אפשר להשתמש בפונקציה SEARCH כדי לחפש בטבלה שלמה או להגביל את החיפוש לעמודות ספציפיות.

חיפוש בטבלה שלמה

השאילתה הבאה מחפשת את הערך bar בכל העמודות בטבלה Logs, ומחזירה את השורות שמכילות את הערך הזה, בלי קשר לאותיות רישיות. מכיוון שאינדקס החיפוש משתמש במנתח הטקסט שמוגדר כברירת מחדל, אין צורך לציין אותו בפונקציה SEARCH.

SELECT * FROM my_dataset.Logs WHERE SEARCH(Logs, 'bar');
+---------+----------------+-------------------------------------------------------+
| Level   | Source         | Message                                               |
+---------+----------------+-------------------------------------------------------+
| INFO    | 65.177.8.234   | Entry Foo-Bar created                                 |
| WARNING | 132.249.240.10 | Entry Foo-Bar already exists, created by 65.177.8.234 |
| INFO    | 94.60.64.181   | Entry Foo-Bar deleted                                 |
| SEVERE  | 4.113.82.10    | Entry Foo-Bar does not exist, deleted by 94.60.64.181 |
+---------+----------------+-------------------------------------------------------+

השאילתה הבאה מחפשת את הערך `94.60.64.181` בכל העמודות בטבלה Logs, ומחזירה את השורות שמכילות את הערך הזה. התגים האלה מאפשרים חיפוש מדויק, ולכן השורה האחרונה בטבלה Logs, שמכילה את הערך 181.94.60.64, מושמטת.

SELECT * FROM my_dataset.Logs WHERE SEARCH(Logs, '`94.60.64.181`');
+---------+----------------+-------------------------------------------------------+
| Level   | Source         | Message                                               |
+---------+----------------+-------------------------------------------------------+
| INFO    | 94.60.64.181   | Entry Foo-Bar deleted                                 |
| SEVERE  | 4.113.82.10    | Entry Foo-Bar does not exist, deleted by 94.60.64.181 |
+---------+----------------+-------------------------------------------------------+

חיפוש בקבוצת משנה של עמודות

בעזרת SEARCH קל לציין קבוצת משנה של עמודות שבהן רוצים לחפש נתונים. השאילתה הבאה מחפשת את הערך 94.60.64.181 בעמודה Message בטבלה Logs, ומחזירה את השורות שמכילות את הערך הזה.

SELECT * FROM my_dataset.Logs WHERE SEARCH(Message, '`94.60.64.181`');
+---------+----------------+-------------------------------------------------------+
| Level   | Source         | Message                                               |
+---------+----------------+-------------------------------------------------------+
| SEVERE  | 4.113.82.10    | Entry Foo-Bar does not exist, deleted by 94.60.64.181 |
+---------+----------------+-------------------------------------------------------+

השאילתה הבאה מחפשת גם בעמודה Source וגם בעמודה Message בטבלה Logs. היא מחזירה את השורות שמכילות את הערך 94.60.64.181 מאחת מהעמודות.

SELECT * FROM my_dataset.Logs WHERE SEARCH((Source, Message), '`94.60.64.181`');
+---------+----------------+-------------------------------------------------------+
| Level   | Source         | Message                                               |
+---------+----------------+-------------------------------------------------------+
| INFO    | 94.60.64.181   | Entry Foo-Bar deleted                                 |
| SEVERE  | 4.113.82.10    | Entry Foo-Bar does not exist, deleted by 94.60.64.181 |
+---------+----------------+-------------------------------------------------------+

אם בטבלה יש הרבה עמודות ואתם רוצים לחפש ברוב העמודות, יכול להיות שיהיה קל יותר לציין רק את העמודות שאתם רוצים להחריג מהחיפוש. השאילתה הבאה מחפשת בכל העמודות בטבלה Logs, חוץ מהעמודה Message. היא מחזירה את השורות של כל העמודות מלבד Message שמכילות את הערך 94.60.64.181.

SELECT *
FROM my_dataset.Logs
WHERE SEARCH(
  (SELECT AS STRUCT Logs.* EXCEPT (Message)), '`94.60.64.181`');
+---------+----------------+---------------------------------------------------+
| Level   | Source         | Message                                           |
+---------+----------------+---------------------------------------------------+
| INFO    | 94.60.64.181   | Entry Foo-Bar deleted                             |
+---------+----------------+---------------------------------------------------+

שימוש בכלי אחר לניתוח טקסט

בדוגמה הבאה נוצרת טבלה בשם contact_info עם אינדקס שמשתמש במנתח הטקסט NO_OP_ANALYZER:

CREATE TABLE my_dataset.contact_info (name STRING, email STRING)
AS (
  SELECT 'Kim Lee' AS name, 'kim.lee@example.com' AS email
  UNION ALL
  SELECT 'Kim' AS name, 'kim@example.com' AS email
  UNION ALL
  SELECT 'Sasha' AS name, 'sasha@example.com' AS email
);
CREATE SEARCH INDEX noop_index ON my_dataset.contact_info(ALL COLUMNS)
OPTIONS (analyzer = 'NO_OP_ANALYZER');
+---------+---------------------+
| name    | email               |
+---------+---------------------+
| Kim Lee | kim.lee@example.com |
| Kim     | kim@example.com     |
| Sasha   | sasha@example.com   |
+---------+---------------------+

השאילתה הבאה מחפשת את הערך Kim בעמודה name ואת הערך kim בעמודה email. מכיוון שאינדקס החיפוש לא משתמש במנתח הטקסט שמוגדר כברירת מחדל, צריך להעביר את שם המנתח לפונקציה SEARCH.

SELECT
  name,
  SEARCH(name, 'Kim', analyzer=>'NO_OP_ANALYZER') AS name_Kim,
  email,
  SEARCH(email, 'kim', analyzer=>'NO_OP_ANALYZER') AS email_kim
FROM
  my_dataset.contact_info;

הפונקציה NO_OP_ANALYZER לא משנה את הטקסט, ולכן הפונקציה SEARCH מחזירה את הערך TRUE רק במקרים של התאמות מדויקות:

+---------+----------+---------------------+-----------+
| name    | name_Kim | email               | email_kim |
+---------+----------+---------------------+-----------+
| Kim Lee | FALSE    | kim.lee@example.com | FALSE     |
| Kim     | TRUE     | kim@example.com     | FALSE     |
| Sasha   | FALSE    | sasha@example.com   | FALSE     |
+---------+----------+---------------------+-----------+

הגדרת האפשרויות של מנתח הטקסט

אפשר להתאים אישית את מנתחי הטקסט LOG_ANALYZER ו-PATTERN_ANALYZER על ידי הוספת מחרוזת בפורמט JSON לאפשרויות ההגדרה. אפשר להגדיר מנתחי טקסט בפונקציה SEARCH, בהצהרת ה-DDL‏ CREATE SEARCH INDEX ובפונקציה TEXT_ANALYZE.

בדוגמה הבאה נוצרת טבלה בשם complex_table עם אינדקס שמשתמש במנתח הטקסט LOG_ANALYZER. הוא משתמש במחרוזת בפורמט JSON כדי להגדיר את אפשרויות הניתוח:

CREATE TABLE dataset.complex_table(
  a STRING,
  my_struct STRUCT<string_field STRING, int_field INT64>,
  b ARRAY<STRING>
);

CREATE SEARCH INDEX my_index
ON dataset.complex_table(a, my_struct, b)
OPTIONS (analyzer = 'LOG_ANALYZER', analyzer_options = '''{
  "token_filters": [
    {
      "normalizer": {"mode": "NONE"}
    }
  ]
}''');

בטבלה הבאה מוצגות דוגמאות לקריאות לפונקציה SEARCH עם מנתחי טקסט שונים והתוצאות שלהן. הטבלה הראשונה קוראת לפונקציה SEARCH באמצעות מנתח הטקסט שמוגדר כברירת מחדל, LOG_ANALYZER:

בקשה להפעלת פונקציה מחזירה סיבה
SEARCH('foobarexample', NULL) שגיאה הערך של search_terms הוא NULL.
SEARCH('foobarexample', '')‎ שגיאה הפרמטר search_terms לא מכיל אסימונים.
SEARCH('foobar-example', 'foobar example') TRUE התווים '-' ו-' ' הם תווים מפרידים.
SEARCH('foobar-example', 'foobarexample')‎ לא נכון הערך search_terms לא מפוצל.
SEARCH('foobar-example', 'foobar\\&example')‎ TRUE הלוכסן ההפוך הכפול מבטל את התו & שהוא תו מפריד.
SEARCH('foobar-example', R'foobar\&example') TRUE הלוכסן ההפוך היחיד משמש כתו בריחה (escape) לאמפרסנד במחרוזת גולמית.
SEARCH('foobar-example', '`foobar&example`') לא נכון התגים דורשים התאמה מדויקת ל-foobar&example.
SEARCH('foobar&example', '`foobar&example`') TRUE נמצאה התאמה מדויקת.
SEARCH('foobar-example', 'example foobar')‎ TRUE אין חשיבות לסדר המונחים.
SEARCH('foobar-example', 'foobar example')‎ TRUE הטוקנים מומרים לאותיות קטנות.
SEARCH('foobar-example', '`foobar-example`')‎ TRUE נמצאה התאמה מדויקת.
SEARCH('foobar-example', '`foobar`')‎ לא נכון תגי Backtick שומרים על אותיות רישיות.
SEARCH('`foobar-example`', '`foobar-example`') לא נכון למירכאות אחוריות אין משמעות מיוחדת ב-data_to_search וב-
SEARCH('foobar@example.com', '`example.com`')‎ TRUE נמצאה התאמה מדויקת אחרי התו המפריד ב-data_to_search.
SEARCH('a foobar-example b', '`foobar-example`')‎ TRUE נמצאה התאמה מדויקת בין התווים המפרידים של הרווחים.
SEARCH(['foobar', 'example'], 'foobar example') לא נכון אין רשומה אחת במערך שתואמת לכל מונחי החיפוש.
SEARCH('foobar=', '`foobar\\=`') לא נכון הערך של search_terms שווה ל-foobar\=.
SEARCH('foobar=', R'`foobar\=`') לא נכון זה שווה ערך לדוגמה הקודמת.
SEARCH('foobar=', 'foobar\\=') TRUE סימן השוויון הוא מפריד בנתונים ובשאילתה.
SEARCH('foobar=', R'foobar\=') TRUE זה שווה ערך לדוגמה הקודמת.
SEARCH('foobar.example', '`foobar`')‎ TRUE נמצאה התאמה מדויקת.
SEARCH('foobar.example', '`foobar.`')‎ לא נכון המחרוזת `foobar.` לא מנותחת בגלל סימני הגרש ההפוך. היא לא
SEARCH('foobar..example', '`foobar.`')‎ TRUE `foobar.` לא מנותח בגלל הגרש ההפוך; אחריו מופיע

בטבלה הבאה מוצגות דוגמאות לקריאות לפונקציה SEARCH באמצעות מנתח הטקסט NO_OP_ANALYZER, וסיבות לערכי החזרה שונים:

בקשה להפעלת פונקציה מחזירה סיבה
SEARCH('foobar', 'foobar', analyzer=>'NO_OP_ANALYZER') TRUE נמצאה התאמה מדויקת.
SEARCH('foobar', '`foobar`', analyzer=>'NO_OP_ANALYZER') לא נכון תגי backtick הם לא תווים מיוחדים ב-NO_OP_ANALYZER.
‎SEARCH('Foobar', 'foobar', analyzer=>'NO_OP_ANALYZER')‎ לא נכון האותיות הרישיות לא תואמות.
SEARCH('foobar example', 'foobar', analyzer=>'NO_OP_ANALYZER') לא נכון אין מפרידים ל-NO_OP_ANALYZER.
SEARCH('', '', analyzer=>'NO_OP_ANALYZER') TRUE אין מפרידים ל-NO_OP_ANALYZER.

אופרטורים ופונקציות אחרים

אתם יכולים לבצע אופטימיזציות של אינדקס החיפוש באמצעות כמה אופרטורים, פונקציות ופרדיקטים.

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

‫BigQuery יכול לבצע אופטימיזציה של שאילתות מסוימות שמשתמשות באופרטור השוויון (=), באופרטור IN, באופרטור LIKE, בפונקציה STARTS_WITH או בפונקציה ENDS_WITH כדי להשוות בין מחרוזות מילוליות לבין נתונים שנוסף להם אינדקס.

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

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

  • column_name = 'string_literal'
  • 'string_literal' = column_name
  • struct_column.nested_field = 'string_literal'
  • string_array_column[OFFSET(0)] = 'string_literal'
  • string_array_column[ORDINAL(1)] = 'string_literal'
  • column_name IN ('string_literal1', 'string_literal2', ...)
  • column_name LIKE 'prefix%'
  • STARTS_WITH(column_name, 'prefix')
  • ENDS_WITH(column_name, 'some suffix')

אופטימיזציה באמצעות פרדיקטים מספריים

אם אינדקס החיפוש נוצר עם סוגי נתונים מספריים, BigQuery יכול לבצע אופטימיזציה של שאילתות מסוימות שמשתמשות באופרטור השוויון (=) או באופרטור IN עם נתונים שנוסף להם אינדקס. אפשר לבצע אופטימיזציה של אינדקס החיפוש באמצעות הפרדיקטים הבאים:

  • INT64(json_column.int64_field) = 1
  • int64_column = 1
  • int64_array_column[OFFSET(0)] = 1
  • int64_column IN (1, 2)
  • struct_column.nested_int64_field = 1
  • struct_column.nested_timestamp_field = TIMESTAMP "2024-02-15 21:31:40"
  • timestamp_column = "2024-02-15 21:31:40"
  • timestamp_column IN ("2024-02-15 21:31:40", "2024-02-16 21:31:40")

אופטימיזציה של פונקציות שמפיקות נתונים שנוספו לאינדקס

‫BigQuery תומך באופטימיזציה של אינדקס החיפוש כשפונקציות מסוימות מופעלות על נתונים שנוסף להם אינדקס. אם אינדקס החיפוש משתמש במנתח הטקסט שמוגדר כברירת מחדל, LOG_ANALYZER, אפשר להחיל על העמודה את הפונקציות UPPER או LOWER, למשל UPPER(column_name) = 'STRING_LITERAL'.

בנתוני מחרוזת סקלריים מסוג JSON שחולצו מעמודה מסוג JSON שנוסף לה אינדקס, אפשר להפעיל את הפונקציה STRING או את הגרסה הבטוחה שלה, SAFE.STRING. אם הערך של JSON שחולץ הוא לא מחרוזת, הפונקציה STRING מייצרת שגיאה והפונקציה SAFE.STRING מחזירה את הערך NULL.

אפשר להחיל את הפונקציות הבאות על נתוני STRING (לא JSON) בפורמט JSON שנוספו לאינדקס:

לדוגמה, נניח שיש לכם את הטבלה הבאה שנוסף לה אינדקס, בשם dataset.person_data, עם העמודות JSON ו-STRING:

+----------------------------------------------------------------+-----------------------------------------+
| json_column                                                    | string_column                           |
+----------------------------------------------------------------+-----------------------------------------+
| { "name" : "Ariel", "email" : "cloudysanfrancisco@gmail.com" } | { "name" : "Ariel", "job" : "doctor" }  |
+----------------------------------------------------------------+-----------------------------------------+

אפשר לבצע אופטימיזציה לשאילתות הבאות:

SELECT * FROM dataset.person_data
WHERE SAFE.STRING(json_column.email) = 'cloudysanfrancisco@gmail.com';
SELECT * FROM dataset.person_data
WHERE JSON_VALUE(string_column, '$.job') IN ('doctor', 'lawyer', 'teacher');

גם שילובים של הפונקציות האלה עוברים אופטימיזציה, למשל UPPER(JSON_VALUE(json_string_expression)) = 'FOO'.

אופטימיזציה באמצעות JSON_FLATTEN

ב-BigQuery יש תמיכה באופטימיזציה של אינדקס החיפוש לשאילתות שמשתמשות בפונקציה JSON_FLATTEN כדי לשטח מערכי JSON, בדרך כלל בשילוב עם EXISTS ו-UNNEST.

לדוגמה, נניח שיש לכם טבלה בשם dataset.logs עם עמודת JSON בשם json_payload. השאילתה הבאה עומדת בדרישות לאופטימיזציה:

SELECT json_payload
FROM dataset.logs
WHERE EXISTS(
  SELECT 1
  FROM UNNEST(JSON_FLATTEN(JSON_QUERY(json_payload, "lax recursive $.message"))) AS f
  WHERE SEARCH(f, "nullpointerexception")
);

השימוש באינדקס החיפוש

כדי לקבוע אם נעשה שימוש באינדקס חיפוש בשאילתה, אפשר להציג את פרטי המשימה או לשלוח שאילתה לאחת מהתצוגות של INFORMATION_SCHEMA.JOBS*.

צפייה בפרטי המשרה

בקטע Job Information של Query results, השדות Index Usage Mode ו-Index Unused Reasons מספקים מידע מפורט על השימוש באינדקס החיפוש.

פרטי המשימה שמסבירים למה לא נעשה שימוש באינדקס החיפוש.

מידע על השימוש באינדקס החיפוש זמין גם דרך השדה searchStatistics ב-API‏ Jobs.Get. השדה indexUsageMode ב-searchStatistics מציין אם נעשה שימוש באינדקס חיפוש עם הערכים הבאים:

  • ‫UNUSED: לא נעשה שימוש באינדקס חיפוש.
  • ‫PARTIALLY_USED: חלק מהשאילתה השתמש באינדקסי חיפוש וחלק לא.
  • ‫FULLY_USED: כל פונקציית SEARCH בשאילתה השתמשה באינדקס חיפוש.

כשהערך של indexUsageMode הוא UNUSED או PARTIALLY_USED, השדה indexUnusedReasons מכיל מידע על הסיבה לכך שלא נעשה שימוש באינדקסי חיפוש בשאילתה.

כדי לראות את searchStatistics של שאילתה, מריצים את הפקודה bq show.

bq show --format=prettyjson -j JOB_ID

דוגמה

נניח שאתם מריצים שאילתה שקוראת לפונקציה SEARCH על נתונים בטבלה. אפשר להציג את פרטי המשימה של השאילתה כדי למצוא את מזהה המשימה, ואז להריץ את הפקודה bq show כדי לראות מידע נוסף:

bq show --format=prettyjson --j my_project:US.bquijob_123x456_789y123z456c

הפלט מכיל שדות רבים, כולל searchStatistics, שנראה בערך כך: בדוגמה הזו, הערך indexUsageMode מציין שלא נעשה שימוש באינדקס. הסיבה לכך היא שלטבלה אין אינדקס חיפוש. כדי לפתור את הבעיה, יוצרים אינדקס חיפוש בטבלה. indexUnusedReason code field מפרט את כל הסיבות לכך שאינדקס החיפוש לא משמש בשאילתה.

"searchStatistics": {
  "indexUnusedReasons": [
    {
      "baseTable": {
        "datasetId": "my_dataset",
        "projectId": "my_project",
        "tableId": "my_table"
      },
      "code": "INDEX_CONFIG_NOT_AVAILABLE",
      "message": "There is no search index configuration for the base table `my_project:my_dataset.my_table`."
    }
  ],
  "indexUsageMode": "UNUSED"
},

שליחת שאילתות לתצוגות של INFORMATION_SCHEMA

אתם יכולים גם לראות את השימוש באינדקס החיפוש של כמה משימות באזור בתצוגות הבאות:

השאילתה הבאה מציגה מידע על השימוש באינדקס לכל השאילתות שאפשר לבצע להן אופטימיזציה של אינדקס החיפוש ב-7 הימים האחרונים:

SELECT
  job_id, search_statistics.index_usage_mode, index_unused_reason.code, index_unused_reason.base_table.table_id, index_unused_reason.index_name
FROM
  `region-REGION_NAME`.INFORMATION_SCHEMA.JOBS, UNNEST(search_statistics.index_unused_reasons) AS index_unused_reason
WHERE
  end_time BETWEEN TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 DAY) AND CURRENT_TIMESTAMP();

התוצאה אמורה להיראות כך:

+-----------+----------------------------------------+-----------------------+
| job_id    | index_usage_mode | code                | table_id | index_name |
+-----------+------------------+---------------------+-----------------------+
| bquxjob_1 | UNUSED           | BASE_TABLE_TOO_SMALL| my_table | my_index   |
| bquxjob_2 | FULLY_USED       | NULL                | my_table | my_index   |
+-----------+----------------------------------------+-----------------------+

שיטות מומלצות

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

חיפוש סלקטיבי

החיפוש פועל בצורה הטובה ביותר כשיש מעט תוצאות. החיפושים צריכים להיות ספציפיים ככל האפשר.

אופטימיזציה של ORDER BY LIMIT

כדי לבצע אופטימיזציה של שאילתות שמשתמשות ב-SEARCH,‏ =,‏ IN,‏ LIKE או STARTS_WITH בטבלה מחולקת למחיצות גדולה מאוד, אפשר להשתמש בסעיף ORDER BY בשדה המחולק למחיצות ובסעיף LIMIT. בשאילתות שלא מכילות את הפונקציה SEARCH, אפשר להשתמש באופרטורים ובפונקציות אחרות כדי לנצל את האופטימיזציה. האופטימיזציה חלה גם אם הטבלה נוספה לאינדקס וגם אם לא. השיטה הזו מתאימה אם אתם מחפשים מונח נפוץ. לדוגמה, נניח שהטבלה Logs שנוצרה קודם חולקה למחיצות לפי עמודה נוספת מסוג DATE בשם day. השאילתה הבאה עברה אופטימיזציה:

SELECT
  Level, Source, Message
FROM
  my_dataset.Logs
WHERE
  SEARCH(Message, "foo")
ORDER BY
  day
LIMIT 10;

כשמשתמשים בפונקציה SEARCH, צריך לחפש רק בעמודות בטבלה שצפויות להכיל את מונחי החיפוש. כך אפשר לשפר את הביצועים ולהפחית את מספר הבייטים שצריך לסרוק.

שימוש בסימני הטעמה משנית (backticks)

כשמשתמשים בפונקציה SEARCH עם מנתח הטקסט LOG_ANALYZER, הוספת מירכאות הפוכות לשאילתת החיפוש מאלצת התאמה מדויקת. זה שימושי אם החיפוש תלוי אותיות רישיות או מכיל תווים שלא אמורים להתפרש כמפרידים. לדוגמה, כדי לחפש את כתובת ה-IP‏ 192.0.2.1, משתמשים ב-`192.0.2.1`. בלי התווים האלה, החיפוש יחזיר כל שורה שמכילה את הטוקנים הנפרדים 192, 0, 2 ו-1, בכל סדר שהוא.