ข้อมูลเบื้องต้นเกี่ยวกับ Cloud Bigtable

ข้อมูลเบื้องต้นเกี่ยวกับ Cloud Bigtable

เกี่ยวกับ Codelab นี้

subjectอัปเดตล่าสุดเมื่อ ม.ค. 24, 2022
account_circleเขียนโดย Billy Jacobson

1 บทนำ

ใน Codelab นี้ คุณจะได้รับคำแนะนำเกี่ยวกับการใช้ Cloud Bigtable กับไคลเอ็นต์ Java HBase

คุณจะได้เรียนรู้วิธีการ

  • หลีกเลี่ยงข้อผิดพลาดที่พบบ่อยด้วยการออกแบบสคีมา
  • นำเข้าข้อมูลในไฟล์ลำดับ
  • ค้นหาข้อมูล

เมื่อดำเนินการเสร็จแล้ว คุณจะมีแผนที่หลายแผนที่ที่แสดงข้อมูลรถประจำทางในนิวยอร์กซิตี้ ตัวอย่างเช่น คุณจะสร้างแผนที่ความนิยมของการเดินทางด้วยรถประจำทางในแมนฮัตตัน:

7349d94f7d41f1d1.png

คุณจะให้คะแนนความพึงพอใจสำหรับประสบการณ์ในการใช้ Google Cloud Platform อย่างไร

คุณจะใช้บทแนะนำนี้อย่างไร

2 เกี่ยวกับชุดข้อมูล

คุณจะเห็นชุดข้อมูลเกี่ยวกับรถโดยสารในนิวยอร์กซิตี้ มีรถประจำทางมากกว่า 300 เส้นทางและยานพาหนะกว่า 5,800 คันไปตามเส้นทางเหล่านั้น ชุดข้อมูลของเราคือบันทึกที่มีชื่อจุดหมาย รหัสยานพาหนะ ละติจูด ลองจิจูด เวลาที่คาดว่าจะมาถึง และเวลาถึงตามกำหนดการ ชุดข้อมูลนี้ประกอบด้วยสแนปชอตที่ถ่ายทุกๆ 10 นาทีในเดือนมิถุนายน 2017

3 การออกแบบสคีมา

หากต้องการประสิทธิภาพที่ดีที่สุดจาก Cloud Bigtable คุณต้องใช้ความรอบคอบเมื่อออกแบบสคีมา ข้อมูลใน Cloud Bigtable จะได้รับการจัดเรียงโดยอัตโนมัติแบบพจนานุกรม ดังนั้นหากคุณออกแบบสคีมาได้ดี การค้นหาข้อมูลที่เกี่ยวข้องจะมีประสิทธิภาพมาก Cloud Bigtable อนุญาตให้มีการค้นหาโดยใช้การค้นหาจุดตามคีย์แถวหรือการสแกนช่วงแถวซึ่งแสดงผลชุดแถวที่ต่อเนื่องกัน อย่างไรก็ตาม หากคุณออกแบบสคีมามาอย่างถี่ถ้วนแล้ว คุณอาจพบว่าตัวเองต้องการค้นหาแถวหลายแถวต่อกัน หรือถ้าแย่กว่านั้นคือการสแกนทั้งตาราง ซึ่งการดำเนินการช้ามาก

วางแผนการค้นหา

ข้อมูลของเรามีข้อมูลที่หลากหลาย แต่สำหรับ Codelab นี้ คุณจะใช้ตำแหน่งและปลายทางของรถบัส

ด้วยข้อมูลดังกล่าว คุณสามารถดำเนินการค้นหาต่อไปนี้

  • ดูตำแหน่งของรถประจำทาง 1 คันใน 1 ชั่วโมง
  • รับข้อมูลที่ตลอดทั้งวันสำหรับสายรถประจำทางหรือรถประจำทางเฉพาะ
  • หาป้ายรถประจำทางทุกคันที่อยู่ในรูปสี่เหลี่ยมผืนผ้าบนแผนที่
  • ดูตำแหน่งปัจจุบันของรถประจำทางทั้งหมด (หากคุณนำเข้าข้อมูลนี้แบบเรียลไทม์)

การสืบค้นชุดนี้ไม่สามารถทำงานร่วมกันได้อย่างมีประสิทธิภาพ เช่น หากจัดเรียงตามเวลา คุณจะสแกนตามตำแหน่งไม่ได้หากไม่สแกนตารางแบบเต็ม คุณต้องจัดลำดับความสำคัญตามคำค้นหาที่ใช้บ่อยที่สุด

สำหรับ Codelab นี้ คุณจะมุ่งเน้นที่การเพิ่มประสิทธิภาพและเรียกใช้ชุดข้อความค้นหาต่อไปนี้

  • รับข้อมูลตำแหน่งของยานพาหนะคันหนึ่งๆ ในช่วง 1 ชั่วโมงขึ้นไป
  • ดูตำแหน่งของรถประจำทางทั้งสายนานกว่า 1 ชั่วโมง
  • ดูตำแหน่งของรถเมล์ทุกคันในแมนฮัตตันภายใน 1 ชั่วโมง
  • ดูตำแหน่งล่าสุดของรถประจำทางทั้งหมดในแมนฮัตตันใน 1 ชั่วโมง
  • ดูตำแหน่งของรถประจำทางทั้งสายในเดือนต่างๆ
  • ดูตำแหน่งของรถบัสทั้งสายที่มีปลายทางนั้นๆ ใน 1 ชั่วโมง

ออกแบบคีย์ประจำแถว

สำหรับ Codelab นี้ คุณจะทำงานกับชุดข้อมูลแบบคงที่ แต่จะออกแบบสคีมาสำหรับความสามารถในการปรับขนาด คุณจะต้องออกแบบสคีมาที่ให้คุณสามารถสตรีมข้อมูลรถประจำทางมากขึ้นลงในตารางและยังคงทำงานได้ดี

สคีมาที่เสนอสําหรับคีย์แถวมีดังนี้

[บริษัทเดินรถประจำทาง/สายรถประจำทาง/การประทับเวลาปัดเศษเป็นชั่วโมง/รหัสยานพาหนะ] แต่ละแถวจะมีข้อมูล 1 ชั่วโมง และแต่ละเซลล์มีข้อมูลเวอร์ชันที่มีการประทับเวลาหลายเวอร์ชัน

สำหรับ Codelab นี้ คุณจะใช้กลุ่มคอลัมน์เดียวเพื่อทำให้ทุกอย่างเรียบง่าย ต่อไปนี้เป็นตัวอย่างมุมมองของข้อมูล ข้อมูลจะจัดเรียงตามคีย์ของแถว

คีย์ประจำแถว

cf:VehicleLocation.Latitude

cf:VehicleLocation.Longitude

...

MTA/M86-SBS/1496275200000/NYCT_5824

40.781212 @20:52:54.0040.776163 @20:43:19.0040.778714 @20:33:46.00

-73.961942 @20:52:54.00-73.946949 @20:43:19.00-73.953731 @20:33:46.00

...

MTA/M86-SBS/1496275200000/NYCT_5840

40.780664 @20:13:51.0040.788416 @20:03:40.00

-73.958357 @20:13:51.00 -73.976748 @20:03:40.00

...

MTA/M86-SBS/1496275200000/NYCT_5867

40.780281 @20:51:45.0040.779961 @20:43:15.0040.788416 @20:33:44.00

-73.946890 @20:51:45.00-73.959465 @20:43:15.00-73.976748 @20:33:44.00

...

...

...

...

...

4 สร้างอินสแตนซ์ ตาราง และครอบครัว

ถัดไป คุณจะสร้างตาราง Cloud Bigtable

ก่อนอื่นให้สร้างโปรเจ็กต์ใหม่ ใช้ Cloud Shell ในตัว ซึ่งเปิดได้โดยคลิก "เปิดใช้งาน Cloud Shell" ที่มุมบนขวา

a74d156ca7862b28.png

ตั้งค่าตัวแปรสภาพแวดล้อมต่อไปนี้เพื่อให้คัดลอกและวางคำสั่ง Codelab ได้ง่ายขึ้น

INSTANCE_ID="bus-instance"
CLUSTER_ID="bus-cluster"
TABLE_ID="bus-data"
CLUSTER_NUM_NODES=3
CLUSTER_ZONE="us-central1-c"

Cloud Shell มาพร้อมกับเครื่องมือที่คุณจะใช้ใน Codelab นี้ เครื่องมือบรรทัดคำสั่ง gcloud อินเทอร์เฟซบรรทัดคำสั่ง cbt และ Maven ที่ติดตั้งไว้แล้ว

เปิดใช้ Cloud Bigtable API โดยการเรียกใช้คำสั่งนี้

gcloud services enable bigtable.googleapis.com bigtableadmin.googleapis.com

สร้างอินสแตนซ์โดยการเรียกใช้คำสั่งต่อไปนี้

gcloud bigtable instances create $INSTANCE_ID \
    --cluster=$CLUSTER_ID \
    --cluster-zone=$CLUSTER_ZONE \
    --cluster-num-nodes=$CLUSTER_NUM_NODES \
    --display-name=$INSTANCE_ID

หลังจากสร้างอินสแตนซ์แล้ว ให้สร้างไฟล์การกำหนดค่า cbt แล้วสร้างกลุ่มตารางและคอลัมน์โดยเรียกใช้คำสั่งต่อไปนี้

echo project = $GOOGLE_CLOUD_PROJECT > ~/.cbtrc
echo instance = $INSTANCE_ID >> ~/.cbtrc

cbt createtable $TABLE_ID
cbt createfamily $TABLE_ID cf

5 นำเข้าข้อมูล

นำเข้าชุดไฟล์ลำดับสำหรับ Codelab นี้จาก gs://cloud-bigtable-public-datasets/bus-data โดยทำตามขั้นตอนต่อไปนี้

เปิดใช้ Cloud Dataflow API โดยเรียกใช้คำสั่งนี้

gcloud services enable dataflow.googleapis.com

เรียกใช้คำสั่งต่อไปนี้เพื่อนำเข้าตาราง

NUM_WORKERS=$(expr 3 \* $CLUSTER_NUM_NODES)
gcloud beta dataflow jobs run import-bus-data-$(date +%s) \
--gcs-location gs://dataflow-templates/latest/GCS_SequenceFile_to_Cloud_Bigtable \
--num-workers=$NUM_WORKERS --max-workers=$NUM_WORKERS \
--parameters bigtableProject=$GOOGLE_CLOUD_PROJECT,bigtableInstanceId=$INSTANCE_ID,bigtableTableId=$TABLE_ID,sourcePattern=gs://cloud-bigtable-public-datasets/bus-data/*

ตรวจสอบการนำเข้า

คุณตรวจสอบงานได้ใน Cloud Dataflow UI นอกจากนี้ คุณยังดูโหลดบนอินสแตนซ์ Cloud Bigtable ได้ด้วย UI การตรวจสอบ การนำเข้าทั้งหมดอาจใช้เวลา 5 นาที

6 รับโค้ด

git clone https://github.com/googlecodelabs/cbt-intro-java.git
cd cbt-intro-java

เปลี่ยนไปใช้ Java 11 โดยเรียกใช้คำสั่งต่อไปนี้

sudo update-java-alternatives -s java-1.11.0-openjdk-amd64 && export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64/

7 ทำการค้นหา

คำค้นหาแรกที่คุณจะดำเนินการคือการค้นหาแถวอย่างง่าย คุณจะได้รับข้อมูลของรถประจำทางบนสาย M86-SBS ในวันที่ 1 มิถุนายน 2017 ตั้งแต่เวลา 00:00 น. ถึง 1:00 น. ยานพาหนะที่มีรหัส NYCT_5824 อยู่บนสายรถประจำทางในเวลาดังกล่าว

เมื่อทราบข้อมูลและทราบถึงการออกแบบสคีมา (บริษัทรถประจำทาง/สายรถประจำทาง/การประทับเวลาที่ปัดเศษเป็นชั่วโมง/รหัสยานพาหนะ) คุณจะอนุมานได้ว่าคีย์ประจำแถวมีลักษณะดังนี้

MTA/M86-SBS/1496275200000/NYCT_5824

BusQueries.java

private static final byte[] COLUMN_FAMILY_NAME = Bytes.toBytes("cf");
private static final byte[] LAT_COLUMN_NAME = Bytes.toBytes("VehicleLocation.Latitude");
private static final byte[] LONG_COLUMN_NAME = Bytes.toBytes("VehicleLocation.Longitude");

String rowKey = "MTA/M86-SBS/1496275200000/NYCT_5824";
Result getResult =
    table
.get(
       
new Get(Bytes.toBytes(rowKey))
           
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
           
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME));

ผลการค้นหาควรระบุตำแหน่งล่าสุดของรถบัสภายในชั่วโมงนั้น แต่คุณต้องการเห็นตำแหน่งทั้งหมด ดังนั้นให้กำหนดจำนวนเวอร์ชันสูงสุดในคำขอรับ

BusQueries.java

Result getResult =
    table
.get(
       
new Get(Bytes.toBytes(rowKey))
           
.setMaxVersions(Integer.MAX_VALUE)
           
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
           
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME));

เรียกใช้คำสั่งต่อไปนี้ใน Cloud Shell เพื่อรับรายการละติจูดและลองจิจูดของรถบัสดังกล่าวในช่วง 1 ชั่วโมง

mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \
-Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \
-Dquery=lookupVehicleInGivenHour

คุณสามารถคัดลอกและวางละติจูดและลองจิจูดลงในแอป MapMaker เพื่อแสดงภาพผลลัพธ์ได้ เมื่อผ่านไป 2-3 เลเยอร์แล้ว คุณจะได้รับแจ้งให้สร้างบัญชีฟรี คุณสามารถสร้างบัญชีหรือลบเลเยอร์ที่มีอยู่ได้เลย Codelab นี้มีการแสดงข้อมูลผ่านภาพสำหรับแต่ละขั้นตอน หากคุณเพียงแค่ต้องการทำตาม ผลลัพธ์ของคำค้นหาแรกมีดังนี้

f1a1fac6051c6210.png

8 ดำเนินการสแกน

ทีนี้เรามาดูข้อมูลทั้งหมดของสายรถประจำทางในชั่วโมงนั้นกัน โค้ดสแกนดูค่อนข้างคล้ายกับโค้ด Get เพียงให้ตำแหน่งเริ่มต้นแก่เครื่องสแกน จากนั้นระบุว่าต้องการให้แสดงเฉพาะแถวสำหรับสายรถประจำทาง M86-SBS ภายในชั่วโมงที่มีการประทับเวลา 1496275200000

BusQueries.java

Scan scan;
scan
= new Scan();
scan
.setMaxVersions(Integer.MAX_VALUE)
   
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
   
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME)
   
.withStartRow(Bytes.toBytes("MTA/M86-SBS/1496275200000"))
   
.setRowPrefixFilter(Bytes.toBytes("MTA/M86-SBS/1496275200000"));
ResultScanner scanner = table.getScanner(scan);

เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์

mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \
-Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \
-Dquery=scanBusLineInGivenHour

c18a4ac6522d08a2.png

แอป Map Maker สามารถแสดงรายการหลายรายการในครั้งเดียว คุณจึงสามารถดูได้ว่ารถบัสคันไหนเป็นยานพาหนะจากข้อความค้นหาแรกที่คุณวิ่ง

234c1b51e3b201e.png

การแก้ไขที่น่าสนใจสำหรับคำค้นหานี้คือการดูข้อมูลทั้งเดือนสำหรับสายรถประจำทาง M86-SBS ซึ่งทำได้ง่ายมาก นําการประทับเวลาออกจากตัวกรองแถวเริ่มต้นและคํานําหน้าเพื่อให้ได้ผลลัพธ์

BusQueries.java

scan.withStartRow(Bytes.toBytes("MTA/M86-SBS/"))
   
.setRowPrefixFilter(Bytes.toBytes("MTA/M86-SBS/"));

// Optionally, reduce the results to receive one version per column
// since there are so many data points.
scan
.setMaxVersions(1);

เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์ (จะมีรายการผลลัพธ์จำนวนมาก)

mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \
-Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \
-Dquery=scanEntireBusLine

หากคุณคัดลอกผลลัพธ์ลงใน MapMaker คุณสามารถดูแผนที่ความหนาแน่นของเส้นทางรถประจำทางได้ หยดน้ำสีส้มแสดงถึงจุดหยุด และหยดน้ำสีแดงสดคือจุดเริ่มต้นและจุดสิ้นสุดของเส้นทาง

346f52e61b3d8902.png

9 ใช้ตัวกรอง

จากนั้น คุณจะกรองรถประจำทางที่มุ่งหน้าไปทางทิศตะวันออกและรถประจำทางที่มุ่งหน้าไปทางตะวันตก และสร้างแผนที่ความหนาแน่นของแต่ละคันแยกกัน

BusQueries.java

Scan scan;
ResultScanner scanner;
scan
= new Scan();
SingleColumnValueFilter valueFilter =
   
new SingleColumnValueFilter(
        COLUMN_FAMILY_NAME
,
       
Bytes.toBytes("DestinationName"),
       
CompareOp.EQUAL,
       
Bytes.toBytes("Select Bus Service Yorkville East End AV"));

scan
.setMaxVersions(1)
   
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
   
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME);
scan
.withStartRow(Bytes.toBytes("MTA/M86-SBS/"))
   
.setRowPrefixFilter(Bytes.toBytes("MTA/M86-SBS/"));
scan
.setFilter(valueFilter);
scanner
= table.getScanner(scan);

เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์ของรถประจำทางที่ไปทางตะวันออก

mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \
-Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \
-Dquery=filterBusesGoingEast

หากต้องการรถเมล์ไปทางทิศตะวันตก ให้เปลี่ยนสตริงใน valueFilter:

BusQueries.java

SingleColumnValueFilter valueFilter =
   
new SingleColumnValueFilter(
        COLUMN_FAMILY_NAME
,
       
Bytes.toBytes("DestinationName"),
       
CompareOp.EQUAL,
       
Bytes.toBytes("Select Bus Service Westside West End AV"));

เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์ของรถประจำทางที่ไปทางทิศตะวันตก

mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \
-Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \
-Dquery=filterBusesGoingWest

รถประจำทางมุ่งหน้าไปทางตะวันออก

76f6f62096a6847a.png

รถประจำทางกำลังมุ่งหน้าทิศตะวันตก

2b5771ee9046399f.png

เมื่อเปรียบเทียบแผนที่ความหนาแน่น 2 แบบ คุณจะเห็นความแตกต่างของเส้นทาง รวมถึงเห็นความแตกต่างของอัตราความเร็ว การตีความข้อมูลอย่างหนึ่งคือระหว่างเส้นทางที่มุ่งหน้าไปทางตะวันตก รถเมล์หยุดวิ่งมากกว่านี้ โดยเฉพาะเมื่อเข้าสู่สวนเซ็นทรัลพาร์ก บนรถประจำทางที่มุ่งหน้าไปทางตะวันออก คุณไม่ค่อยเห็นจุดสตาร์ทรถมากนัก

10 ทำการสแกนหลายช่วง

สำหรับคำค้นหาสุดท้าย คุณจะต้องจัดการกับกรณีของกรณีที่คุณสนใจเกี่ยวกับสายรถเมล์หลายสายในพื้นที่

BusQueries.java

private static final String[] MANHATTAN_BUS_LINES = {"M1","M2","M3",...

Scan scan;
ResultScanner scanner;
List<RowRange> ranges = new ArrayList<>();
for (String busLine : MANHATTAN_BUS_LINES) {
  ranges
.add(
     
new RowRange(
         
Bytes.toBytes("MTA/" + busLine + "/1496275200000"), true,
         
Bytes.toBytes("MTA/" + busLine + "/1496275200001"), false));
}
Filter filter = new MultiRowRangeFilter(ranges);
scan
= new Scan();
scan
.setFilter(filter);
scan
.setMaxVersions(Integer.MAX_VALUE)
   
.addColumn(COLUMN_FAMILY_NAME, LAT_COLUMN_NAME)
   
.addColumn(COLUMN_FAMILY_NAME, LONG_COLUMN_NAME);
scan
.withStartRow(Bytes.toBytes("MTA/M")).setRowPrefixFilter(Bytes.toBytes("MTA/M"));
scanner
= table.getScanner(scan);

เรียกใช้คำสั่งต่อไปนี้เพื่อรับผลลัพธ์

mvn package exec:java -Dbigtable.projectID=$GOOGLE_CLOUD_PROJECT \
-Dbigtable.instanceID=$INSTANCE_ID -Dbigtable.table=$TABLE_ID \
-Dquery=scanManhattanBusesInGivenHour

7349d94f7d41f1d1.png

11 ดำเนินการให้เสร็จสิ้น

ล้างข้อมูลเพื่อหลีกเลี่ยงการเรียกเก็บเงิน

คุณควรลบอินสแตนซ์เพื่อเลี่ยงไม่ให้เกิดการเรียกเก็บเงินกับบัญชี Google Cloud Platform สำหรับทรัพยากรที่ใช้ใน Codelab นี้

gcloud bigtable instances delete $INSTANCE_ID

หัวข้อที่ครอบคลุม

  • การออกแบบสคีมา
  • การตั้งค่าอินสแตนซ์ ตาราง และครอบครัว
  • การนำเข้าไฟล์ลำดับด้วยโฟลว์ข้อมูล
  • การค้นหาด้วยการค้นหา การสแกน การสแกนด้วยตัวกรอง และการสแกนแบบหลายช่วง

ขั้นตอนถัดไป