יצירת טבלה חיצונית של Bigtable

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

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

לפני שמתחילים

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

התפקידים הנדרשים

כדי ליצור טבלה חיצונית שמשמשת לשאילתות על נתוני Bigtable, אתם צריכים להיות חשבון משתמש עם התפקיד "אדמין ב-Bigtable" (roles/bigtable.admin) במכונה שמכילה את טבלת המקור.

אתם צריכים גם את ההרשאה bigquery.tables.create לניהול זהויות והרשאות גישה (IAM) ב-BigQuery.

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

  • עריכה של נתוני BigQuery‏ (roles/bigquery.dataEditor)
  • בעלי הנתונים ב-BigQuery‏ (roles/bigquery.dataOwner)
  • אדמין ב-BigQuery‏ (roles/bigquery.admin)

אם אין לכם אף אחד מהתפקידים האלה, בקשו מהאדמין לתת לכם גישה או ליצור בשבילכם את הטבלה החיצונית.

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

יצירה או זיהוי של מערך נתונים

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

תכנון השימוש במשאבי המחשוב

קובעים את סוג המחשוב שבו רוצים להשתמש כששולחים שאילתות לנתונים. בהגדרות של פרופיל האפליקציה אתם מציינים אם אתם רוצים להשתמש ב-Data Boost או לנתב לאשכול ייעודי.

Data Boost

כדי לא להשפיע על תעבורת הנתונים של האפליקציה, אתם יכולים להשתמש במחשוב בלי שרת (serverless computing) של Data Boost כשאתם משתמשים בטבלה חיצונית של BigQuery כדי לקרוא את נתוני Bigtable. כדי להשתמש ב-Data Boost, צריך להשתמש בפרופיל אפליקציה של Data Boost ולכלול את מזהה פרופיל האפליקציה כשיוצרים את ה-URI של Bigtable. מידע נוסף זמין במאמר סקירה כללית על Bigtable Data Boost.

צמתים מוקצים

אם אתם לא משתמשים ב-Data Boost, צומתי האשכול משמשים למחשוב.

אם אתם לא משתמשים ב-Data Boost ומתכננים לשלוח שאילתות לעיתים קרובות לאותם נתונים שמשמשים את אפליקציית הייצור, מומלץ להקצות אשכול במכונה של Bigtable שישמש רק לניתוח ב-BigQuery. כך אפשר לבודד את התנועה מהאשכול או מהאשכולות שמשמשים לקריאות ולכתיבות של האפליקציה. במאמר מידע על רפליקציה מוסבר איך ליצור מכונות עם יותר מאשכול אחד.

זיהוי או יצירה של פרופיל אפליקציה

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

אם יש לכם אשכול במכונה של Bigtable שמיועד לגישה ל-BigQuery, הגדירו את פרופיל האפליקציה כך שישתמש בניתוב לאשכול יחיד לאותו אשכול.

כדי להשתמש במחשוב בלי שרת (serverless computing) של Data Boost, צריך ליצור פרופיל אפליקציה של Data Boost. כדי להשתמש בצומתי אשכולות לצורך עיבוד, צריך ליצור פרופיל אפליקציה רגיל. במאמר מידע על פרופילי אפליקציות מוסבר איך פועלים פרופילי אפליקציות ב-Bigtable. במאמר יצירה והגדרה של פרופילי אפליקציות מוסבר איך יוצרים פרופיל אפליקציה חדש.

אחזור ה-URI של Bigtable

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

  1. פותחים את הדף Bigtable במסוף.

    כניסה ל-Bigtable

  2. אחזור הפרטים הבאים על מקור הנתונים ב-Bigtable:

    • מזהה הפרויקט שלכם.
    • מזהה המכונה שלכם ב-Bigtable.
    • המזהה של פרופיל האפליקציה ב-Bigtable שבו אתם מתכננים להשתמש. זה יכול להיות פרופיל אפליקציה רגיל או פרופיל אפליקציה של Data Boost, בהתאם לסוג המחשוב שבו אתם רוצים להשתמש. אם לא מציינים מזהה פרופיל אפליקציה, המערכת משתמשת בפרופיל האפליקציה שמוגדר כברירת מחדל.
    • השם של טבלת Bigtable.
  3. יוצרים את ה-URI של Bigtable בפורמט הבא, כאשר:

    • ‫PROJECT_ID הוא הפרויקט שמכיל את המכונה של Bigtable
    • ‫INSTANCE_ID הוא מזהה המכונה של Bigtable
    • ‫APP_PROFILE (אופציונלי) הוא המזהה של פרופיל האפליקציה שבו רוצים להשתמש.
    • ‫TABLE_NAME הוא שם הטבלה ששולחים אליה שאילתה.

    https://googleapis.com/bigtable/projects/PROJECT_ID/instances/INSTANCE_ID[/appProfiles/APP_PROFILE]/tables/TABLE_NAME

יצירת טבלאות חיצוניות קבועות

כשיוצרים טבלה חיצונית קבועה ב-BigQuery שמקושרת למקור נתונים ב-Bigtable, יש שתי אפשרויות להגדרת הפורמט של הטבלה החיצונית:

  • אם אתם משתמשים ב-API או בכלי שורת הפקודה של BigQuery, אתם צריכים ליצור קובץ הגדרת טבלה שמגדיר את הסכימה והמטא-נתונים של הטבלה החיצונית.
  • אם אתם משתמשים ב-SQL, אתם משתמשים באפשרות uri של ההצהרה CREATE EXTERNAL TABLE כדי לציין את טבלת Bigtable שממנה אתם רוצים לשלוף נתונים, ובאפשרות bigtable_options כדי לציין את סכימת הטבלה.

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

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

SQL

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

  1. נכנסים לדף BigQuery במסוף Google Cloud .

    כניסה ל-BigQuery

  2. בעורך השאילתות, מזינים את ההצהרה הבאה:

    CREATE EXTERNAL TABLE DATASET.NEW_TABLE
    OPTIONS (
      format = 'CLOUD_BIGTABLE',
      uris = ['URI'],
      bigtable_options = BIGTABLE_OPTIONS );

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫DATASET: מערך הנתונים שבו יוצרים את הטבלה החיצונית של Bigtable.
    • ‫NEW_TABLE: השם של הטבלה החיצונית ב-Bigtable.
    • ‫URI: ה-URI של טבלת Bigtable שבה רוצים להשתמש כמקור נתונים. ה-URI הזה צריך להיות בפורמט שמתואר בקטע אחזור ה-URI של Bigtable.
    • ‫BIGTABLE_OPTIONS: הסכימה של טבלת Bigtable בפורמט JSON. רשימה של אפשרויות להגדרת טבלאות Bigtable מופיעה במאמר BigtableOptions במאמרי העזרה של ה-API בארכיטקטורת REST.

  3. לוחצים על הפעלה.

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

הצהרה ליצירת טבלה חיצונית של Bigtable עשויה להיראות כך:

CREATE EXTERNAL TABLE mydataset.BigtableTable
OPTIONS (
  format = 'CLOUD_BIGTABLE',
  uris = ['https://googleapis.com/bigtable/projects/myproject/instances/myBigtableInstance/appProfiles/myAppProfile/tables/table1'],
  bigtable_options =
    """
    {
      columnFamilies: [
        {
          "familyId": "familyId1",
          "type": "INTEGER",
          "encoding": "BINARY"
        }
      ],
      readRowkeyAsString: true
    }
    """
);

BQ

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

  1. משתמשים בפקודה bq mk כדי ליצור טבלה קבועה.

    bq mk \
    --external_table_definition=DEFINITION_FILE \
    DATASET.TABLE

    מחליפים את מה שכתוב בשדות הבאים:

    • ‫DEFINITION_FILE: הנתיב לקובץ הגדרת הטבלה במחשב המקומי.
    • ‫DATASET: שם מערך הנתונים שמכיל את הטבלה.
    • ‫TABLE: שם הטבלה שיוצרים.

API

משתמשים ב-method ‏tables.insert של ה-API ויוצרים ExternalDataConfiguration במשאב Table שמעבירים.

במאפיין sourceUris במשאב Table, ציינו רק URI אחד של Bigtable. זו צריכה להיות כתובת URL תקינה מסוג HTTPS.

במאפיין sourceFormat, מציינים את הערך "BIGTABLE".

Java

לפני שמנסים את הדוגמה הזו, צריך לפעול לפי הוראות ההגדרה של Java במדריך למתחילים של BigQuery באמצעות ספריות לקוח. למידע נוסף, קראו את מאמרי העזרה של BigQuery Java API.

כדי לבצע אימות ב-BigQuery, צריך להגדיר את Application Default Credentials. מידע נוסף זמין במאמר הגדרת אימות לספריות לקוח.

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.BigtableColumn;
import com.google.cloud.bigquery.BigtableColumnFamily;
import com.google.cloud.bigquery.BigtableOptions;
import com.google.cloud.bigquery.ExternalTableDefinition;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.TableId;
import com.google.cloud.bigquery.TableInfo;
import com.google.cloud.bigquery.TableResult;
import com.google.common.collect.ImmutableList;
import org.apache.commons.codec.binary.Base64;

// Sample to queries an external bigtable data source using a permanent table
public class QueryExternalBigtablePerm {

  public static void main(String[] args) {
    // TODO(developer): Replace these variables before running the sample.
    String projectId = "MY_PROJECT_ID";
    String bigtableInstanceId = "MY_INSTANCE_ID";
    String bigtableTableName = "MY_BIGTABLE_NAME";
    String bigqueryDatasetName = "MY_DATASET_NAME";
    String bigqueryTableName = "MY_TABLE_NAME";
    String sourceUri =
        String.format(
            "https://googleapis.com/bigtable/projects/%s/instances/%s/tables/%s",
            projectId, bigtableInstanceId, bigtableTableName);
    String query = String.format("SELECT * FROM %s ", bigqueryTableName);
    queryExternalBigtablePerm(bigqueryDatasetName, bigqueryTableName, sourceUri, query);
  }

  public static void queryExternalBigtablePerm(
      String datasetName, String tableName, String sourceUri, String query) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      BigtableColumnFamily.Builder statsSummary = BigtableColumnFamily.newBuilder();

      // Configuring Columns
      BigtableColumn connectedCell =
          BigtableColumn.newBuilder()
              .setQualifierEncoded(Base64.encodeBase64String("connected_cell".getBytes()))
              .setFieldName("connected_cell")
              .setType("STRING")
              .setEncoding("TEXT")
              .build();
      BigtableColumn connectedWifi =
          BigtableColumn.newBuilder()
              .setQualifierEncoded(Base64.encodeBase64String("connected_wifi".getBytes()))
              .setFieldName("connected_wifi")
              .setType("STRING")
              .setEncoding("TEXT")
              .build();
      BigtableColumn osBuild =
          BigtableColumn.newBuilder()
              .setQualifierEncoded(Base64.encodeBase64String("os_build".getBytes()))
              .setFieldName("os_build")
              .setType("STRING")
              .setEncoding("TEXT")
              .build();

      // Configuring column family and columns
      statsSummary
          .setColumns(ImmutableList.of(connectedCell, connectedWifi, osBuild))
          .setFamilyID("stats_summary")
          .setOnlyReadLatest(true)
          .setEncoding("TEXT")
          .setType("STRING")
          .build();

      // Configuring BigtableOptions is optional.
      BigtableOptions options =
          BigtableOptions.newBuilder()
              .setIgnoreUnspecifiedColumnFamilies(true)
              .setReadRowkeyAsString(true)
              .setColumnFamilies(ImmutableList.of(statsSummary.build()))
              .build();

      TableId tableId = TableId.of(datasetName, tableName);
      // Create a permanent table linked to the Bigtable table
      ExternalTableDefinition externalTable =
          ExternalTableDefinition.newBuilder(sourceUri, options).build();
      bigquery.create(TableInfo.of(tableId, externalTable));

      // Example query
      TableResult results = bigquery.query(QueryJobConfiguration.of(query));

      results
          .iterateAll()
          .forEach(row -> row.forEach(val -> System.out.printf("%s,", val.toString())));

      System.out.println("Query on external permanent table performed successfully.");
    } catch (BigQueryException | InterruptedException e) {
      System.out.println("Query not performed \n" + e.toString());
    }
  }
}

הרצת שאילתות על טבלאות חיצוניות

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

סכימה שנוצרה

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

דוגמה

אתם שומרים פרופילי משתמשים ברשת חברתית דמיונית. מודל נתונים אחד לכך יכול להיות קבוצת עמודות profile עם עמודות נפרדות ל-gender, ל-age ול-email:

rowkey | profile:gender| profile:age| profile:email
-------| --------------| -----------| -------------
alice  | female        | 30         | alice@gmail.com

בסכימת ברירת המחדל, שאילתת GoogleSQL לספירת מספר המשתמשים הגברים מעל גיל 30 היא:

SELECT
  COUNT(1)
FROM
  `dataset.table`
OMIT
  RECORD IF NOT SOME(profile.column.name = "gender"
    AND profile.column.cell.value = "male")
  OR NOT SOME(profile.column.name = "age"
    AND INTEGER(profile.column.cell.value) > 30)

הרבה יותר קל לשלוח שאילתות לגבי הנתונים אם gender ו-age חשופים כשדות משנה. כדי לחשוף אותם כשדות משנה, צריך לציין את gender ו-age כעמודות עם שם בקבוצת העמודות profile כשמגדירים את הטבלה. אפשר גם להורות ל-BigQuery לחשוף את הערכים האחרונים מקבוצת העמודות הזו, כי בדרך כלל רק הערך האחרון (ואולי הערך היחיד) מעניין.

אחרי שחושפים את העמודות כשדות משנה, שאילתת GoogleSQL לספירת מספר המשתמשים הגברים מעל גיל 30 היא:

SELECT
  COUNT(1)
FROM
  `dataset.table`
WHERE
  profile.gender.cell.value="male"
  AND profile.age.cell.value > 30

שימו לב שהשדות gender ו-age מאוזכרים ישירות כשדות. הגדרת ה-JSON של ההגדרה הזו היא:

  "bigtableOptions": {
    "readRowkeyAsString": "true",
    "columnFamilies": [
      {
          "familyId": "profile",
          "onlyReadLatest": "true",
          "columns": [
              {
                  "qualifierString": "gender",
                  "type": "STRING"
              },
              {
                  "qualifierString": "age",
                  "type": "INTEGER"
              }
          ]
      }
    ]
  }

קידוד ערכים

ב-Bigtable הנתונים מאוחסנים כבייטים גולמיים, ללא תלות בקידוד הנתונים. עם זאת, לערכי בייטים יש שימוש מוגבל בניתוח שאילתות SQL. ב-Bigtable יש שני סוגים בסיסיים של פענוח סקלרי: טקסט ו-HBase-binary.

בפורמט הטקסט, המערכת מניחה שכל הערכים מאוחסנים כמחרוזות טקסט אלפאנומריות. לדוגמה, המספר השלם 768 יישמר כמחרוזת "768". הקידוד הבינארי מניח שנעשה שימוש במחלקה Bytes.toBytes של שיטות HBase כדי לקודד את הנתונים, ומפעיל שיטת פענוח מתאימה.

אזורים ותחומים נתמכים

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

מגבלות

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

היקפי הרשאות למכונות של Compute Engine

כשיוצרים מכונה של Compute Engine, אפשר לציין רשימה של היקפי הרשאות למכונה. היקפי ההרשאות קובעים את הגישה של המכונה למוצרי Google Cloud, כולל Bigtable. אפליקציות שפועלות במכונה הווירטואלית משתמשות בחשבון השירות כדי לשלוח קריאות לממשקי ה-API של Google Cloud .

אם אתם מגדירים מכונה של Compute Engine כך שתפעל כחשבון שירות, וחשבון השירות הזה ניגש לטבלה חיצונית שמקושרת למקור נתונים של Bigtable, אתם צריכים להוסיף למכונה את היקף הגישה לנתונים לקריאה בלבד של Bigtable‏ (https://www.googleapis.com/auth/bigtable.data.readonly). מידע נוסף זמין במאמר יצירת מכונה של Compute Engine ל-Bigtable.

במאמר שינוי חשבון השירות והיקפי הגישה של מכונה מוסבר איך להחיל היקפי הרשאות על מכונה של Compute Engine. מידע נוסף על חשבונות שירות של Compute Engine זמין במאמר חשבונות שירות.

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