Spanner תומך באינדקסים לחיפוש עם חלוקה למחיצות וגם בלי חלוקה למחיצות. בדף הזה מוסבר איך ליצור אינדקס חיפוש עם חלוקה למחיצות ב-Spanner.
אינדקס לא מחולק נוצר כשמשמיטים את פסוקית PARTITION BY בהגדרת האינדקס. באינדקס לא מחולק, שאילתה צריכה לקרוא מכל הפיצולים של האינדקס. כך מוגבלת יכולת ההתאמה של שאילתות חיפוש בטקסט מלא.
לעומת זאת, אינדקסים מחולקים מחלקים את האינדקס ליחידות קטנות יותר, אחת לכל מחיצה ייחודית. אפשר להריץ שאילתות רק במחיצה אחת בכל פעם, שמוגדרת באמצעות תנאי שוויון בסעיף WHERE. בדרך כלל, שאילתות שמופעלות על אינדקסים עם מחיצות יעילות יותר משאילתות שמופעלות על אינדקסים ללא מחיצות, כי Spanner צריך לקרוא נתונים רק ממחיצה אחת. חלוקת אינדקס החיפוש דומה לקידומת המפתח של אינדקס משני.
לדוגמה, נניח שיש מיליון רשומות SingerIds במסד נתונים ושני האינדקסים הבאים:
GoogleSQL
CREATE TABLE Albums (
AlbumId STRING(MAX) NOT NULL,
SingerId STRING(MAX) NOT NULL,
ReleaseTimestamp INT64 NOT NULL,
AlbumTitle STRING(MAX),
AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
SingerId_Tokens TOKENLIST AS (TOKEN(SingerId)) HIDDEN
) PRIMARY KEY(SingerId, AlbumId);
CREATE SEARCH INDEX AlbumsUnpartitionedIndex
ON Albums(AlbumTitle_Tokens, SingerId_Tokens);
CREATE SEARCH INDEX AlbumsIndexBySingerId
ON Albums(AlbumTitle_Tokens)
PARTITION BY SingerId;
PostgreSQL
CREATE TABLE albums (
albumid character varying NOT NULL,
singerid character varying NOT NULL,
releasetimestamp bigint NOT NULL,
albumtitle character varying,
albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,
singerid_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.token(singerid)) VIRTUAL HIDDEN,
PRIMARY KEY(singerid, albumid));
CREATE SEARCH INDEX albumsunpartitionedindex
ON albums(albumtitle_tokens, singerid_tokens);
CREATE SEARCH INDEX albumsindexbysingerid
ON albums(albumtitle_tokens)
PARTITION BY singerid;
השאילתה הבאה בוחרת את האינדקס AlbumsIndexBySingerId כי היא מחפשת נתונים רק על זמר אחד. בדרך כלל, שאילתות מסוג זה צורכות פחות משאבים.
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SingerId = "singer1"
AND SEARCH(AlbumTitle_Tokens, 'happy')
PostgreSQL
SELECT albumid
FROM albums
WHERE singerid = 'singer1'
AND spanner.search(albumtitle_tokens, 'happy')
אפשר גם לכפות על שאילתה להשתמש ב-AlbumsUnpartitionedIndex כדי להחזיר את אותן תוצאות.
עם זאת, היא משתמשת ביותר משאבים, כי השאילתה צריכה לגשת לכל פיצולי האינדקס ולסנן את כל האלבומים של כל הזמרים כדי למצוא את הטוקן happy, ולא רק את הפיצולים שמתאימים לזמר singer1.
עם זאת, יש מקרים שבהם האפליקציה צריכה לחפש בכל האלבומים ולא רק באלבומים של זמר ספציפי. במקרים האלה, צריך להשתמש באינדקס לא מחולק:
GoogleSQL
SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'piano concerto 1')
PostgreSQL
SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'piano concerto 1')
ההמלצה הכללית היא להשתמש בחלוקה למחיצות ברמת הגרנולריות הכי גבוהה שאפשר, שמתאימה לשאילתה. לדוגמה, אם האפליקציה שולחת שאילתות לתיבת דואר, כאשר כל שאילתה מוגבלת לתיבת דואר ספציפית, צריך לחלק את אינדקס החיפוש לפי מזהה תיבת הדואר. עם זאת, אם השאילתה צריכה לחפש בכל תיבות הדואר, אינדקס לא מחולק מתאים יותר.
יכול להיות שאפליקציות מסוימות ידרשו כמה אסטרטגיות חלוקה כדי להתאים לדרישות החיפוש הספציפיות שלהן. לדוגמה, מערכת לניהול מלאי יכולה לתמוך בשאילתות שמסוננות לפי סוג מוצר או יצרן. בנוסף, יכול להיות שיהיה צורך במיון מראש של חלק מהאפליקציות, למשל מיון לפי זמן היצירה או השינוי. במקרים כאלה, מומלץ ליצור כמה אינדקסים של חיפוש, שכל אחד מהם מותאם לשאילתות המתאימות. כלי האופטימיזציה של שאילתות ב-Spanner בוחר באופן אוטומטי אינדקס לכל שאילתה.
המאמרים הבאים
- מידע על יצירת טוקנים ועל כלי ליצירת טוקנים ב-Spanner
- מידע נוסף על אינדקסים של חיפושים
- מידע על אינדקסים מספריים