שאילתה עם מסנני טווח ואי-שוויון בסקירה כללית של כמה נכסים

‫Firestore במצב Datastore תומך בשימוש במסנני טווח ומסנני אי-שוויון בכמה מאפיינים בשאילתה אחת. התכונה הזו מאפשרת להגדיר תנאים של טווח ואי-שוויון בכמה מאפיינים, ומפשטת את פיתוח האפליקציות על ידי העברת ההטמעה של לוגיקת הסינון לאחר השליפה אל Firestore במצב Datastore.

מסנני טווח ואי-שוויון בכמה נכסים

השאילתה הבאה משתמשת במסנני טווח בעמודות 'עדיפות' ו'ימים' כדי להחזיר את כל המשימות עם עדיפות גבוהה מ-4 ועם פחות מ-3 ימים עד להשלמה.

המשך

query := datastore.NewQuery("Task").
   FilterField("priority", ">", 4).
   FilterField("days", "<", 3).

GQL

SELECT * FROM /tasks WHERE priority > 4 AND days < 3;

Java

Query<Entity> query =
    Query.newEntityQueryBuilder()
      .setKind("Task")
      .setFilter(
        CompositeFilter.and(
            PropertyFilter.gt("priority", 4), PropertyFilter.lt("days", 3)))
    .build();

Node.js

const query = datastore
  .createQuery('Task')
  .filter(
    and([
      new PropertyFilter('priority', '>', 4),
      new PropertyFilter('days', '<', 3),
    ])
  );

Python

from google.cloud import datastore
client = datastore.Client()
query = client.query(kind="Task")
query.add_filter(filter=PropertyFilter("priority", ">", 4))
query.add_filter(filter=PropertyFilter("days", "<", 3))

PHP

$query = $datastore->query()
    ->kind('Task')
    ->filter('priority', '>', 4)
    ->filter('days', '<', 3)

C#‎

Query query = new Query("Task")
{
  Filter = Filter.And(Filter.GreaterThan("priority", 4),
    Filter.LessThan("days", 3))
};

Ruby

query = datastore.query("Task")
                 .where("priority", ">", 4)
                 .where("days", "<", 3)

שיקולים בהוספה לאינדקס

לפני שמתחילים להריץ שאילתות, חשוב לקרוא על שאילתות.

אם לא מציינים פסקה של ORDER BY, Firestore במצב Datastore משתמש בכל אינדקס שיכול לעמוד בתנאי הסינון של השאילתה כדי להציג את השאילתה. הגישה הזו יוצרת קבוצת תוצאות שמסודרת לפי הגדרת האינדקס.

כדי לשפר את הביצועים ולצמצם את העלויות של שאילתות ב-Firestore במצב Datastore, כדאי לשפר את הסדר של המאפיינים באינדקס. כדי לעשות את זה, צריך לוודא שהאינדקס מסודר משמאל לימין, כך שהשאילתה תצמצם את מערך הנתונים ותמנע סריקה של רשומות אינדקס מיותרות.

לדוגמה, נניח שאתם רוצים לחפש אוסף של עובדים כדי למצוא עובדים בארצות הברית שהמשכורת שלהם גבוהה מ-100,000 $ומספר שנות הניסיון שלהם גדול מ-0. בהתאם להבנה שלך לגבי מערך הנתונים, ברור לך שהאילוץ של השכר הוא סלקטיבי יותר מהאילוץ של הניסיון. אינדקס שמצמצם את מספר הסריקות של האינדקס הוא אינדקס (salary [...], experience [...]). כתוצאה מכך, שאילתה מהירה וחסכונית בעלויות מזמינה את salary לפני experience, כמו שמוצג בדוגמה הבאה:

GQL

SELECT *
FROM /employees
WHERE salary > 100000 AND experience > 0
ORDER BY salary, experience

Java

Query<Entity> query =
  Query.newEntityQueryBuilder()
    .setKind("employees")
    .setFilter(
        CompositeFilter.and(
            PropertyFilter.gt("salary", 100000), PropertyFilter.gt("experience", 0)))
    .setOrderBy(OrderBy("salary"), OrderBy("experience"))
    .build();

Node.js

const query = datastore
  .createQuery("employees")
  .filter(
    and([
      new PropertyFilter("salary", ">", 100000),
      new PropertyFilter("experience", ">", 0),
       ])
    )
  .order("salary")
  .order("experience");

Python

query = client.query(kind="employees")
query.add_filter("salary", ">", 100000)
query.add_filter("experience", ">", 0)
query.order = ["-salary", "-experience"]

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

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

סדר השאילתות לפי שדות של שוויון, ואחריהם לפי שדות של טווח או אי-שוויון עם הכי הרבה אפשרויות

ב-Firestore במצב Datastore, המערכת משתמשת במאפיינים הימניים ביותר של אינדקס מורכב כדי לעמוד באילוצי השוויון ובאילוצי הטווח והאי-שוויון, אם יש כאלה, בשדה הראשון של השאילתה orderBy(). המגבלות האלה יכולות לצמצם את מספר רשומות האינדקס ש-Firestore במצב Datastore סורק. מערכת Firestore במצב Datastore משתמשת בשאר המאפיינים של האינדקס כדי לעמוד במגבלות אחרות של טווח ואי-שוויון של השאילתה. המגבלות האלה לא מפחיתות את מספר הרשומות באינדקס ש-Firestore במצב Datastore סורק, אבל הן מסננות ישויות שלא תואמות כך שמספר הישויות שמוחזרות ללקוחות קטן יותר.

מידע נוסף על יצירת אינדקסים יעילים זמין במאמרים מבנה והגדרה של אינדקסים ואופטימיזציה של אינדקסים.

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

כדי לוודא ש-Firestore במצב Datastore בוחר את האינדקס האופטימלי לשאילתה, צריך לציין פסקה orderBy() שמסדרת את מאפייני הטווח והאי-שוויון לפי מידת הסלקטיביות של האילוצים שלהם בשאילתה, החל מהסלקטיבי ביותר. סלקטיביות גבוהה מתאימה לפחות ישויות, וסלקטיביות נמוכה מתאימה ליותר ישויות. בסדר האינדקס, צריך להציב מאפיינים של טווח ואי-שוויון עם סלקטיביות גבוהה יותר לפני מאפיינים עם סלקטיביות נמוכה יותר.

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

לדוגמה, אם רוצים לחפש אוסף של עובדים כדי למצוא עובדים בארצות הברית שהמשכורת שלהם גבוהה מ-100,000 $ולסדר את התוצאות לפי שנת הניסיון של העובד. אם אתם צופים שרק למספר קטן של עובדים תהיה משכורת גבוהה מ-100,000$, הדרך היעילה לכתוב את השאילתה היא כדלקמן:

Java

Query<Entity> query =
  Query.newEntityQueryBuilder()
    .setKind("employees")
    .setFilter(PropertyFilter.gt("salary", 100000))
    .setOrderBy(OrderBy("salary"))
    .build();
QueryResults<Entity> results = datastore.run(query);
// Order results by `experience`

Node.js

const query = datastore
  .createQuery("employees")
  .filter(new PropertyFilter("salary", ">", 100000))
  .order("salary");
const [entities] = await datastore.runQuery(query);
// Order results by `experience`

Python

query = client.query(kind="employees")
query.add_filter("salary", ">", 100000)
query.order = ["salary"]
results = query.fetch()
// Order results by `experience`

הוספת סדר לexperience לשאילתה תניב את אותה קבוצה של ישויות ותמנע את הסידור מחדש של התוצאות בלקוחות, אבל יכול להיות שהשאילתה תעיין בהרבה יותר רשומות אינדקס מיותרות מאשר השאילתה הקודמת. הסיבה לכך היא ש-Firestore במצב Datastore תמיד מעדיף אינדקס שהקידומת של מאפייני האינדקס שלו תואמת לסעיף order by של השאילתה. אם experience נוסף לסעיף order by,‏ Firestore במצב Datastore יבחר את האינדקס (experience [...], salary [...]) לחישוב תוצאות השאילתה. מכיוון שאין אילוצים אחרים על experience, מערכת Firestore במצב Datastore תקרא את כל רשומות האינדקס של האוסף employees לפני שתחיל את המסנן salary כדי למצוא את קבוצת התוצאות הסופית. המשמעות היא שרשומות באינדקס שלא עומדות בדרישות של salaryהמסנן עדיין נקראות, ולכן זמן האחזור והעלות של השאילתה גדלים.

תמחור

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

מידע מפורט זמין בדף תמחור.

מגבלות

בנוסף למגבלות על שאילתות, חשוב לשים לב למגבלות הבאות לפני שמשתמשים בשאילתות עם מסנני טווח ואי-שוויון בכמה נכסים:

  • כדי למנוע מצב שבו עלות ההרצה של שאילתות תהיה גבוהה מדי, ב-Firestore במצב Datastore מוגבל מספר האופרטורים של טווח או אי-שוויון ל-10.

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