เกี่ยวกับ Codelab นี้
1 บทนำ
ใน Codelab นี้ คุณจะได้รับคำแนะนำเกี่ยวกับการใช้ Cloud Bigtable กับไคลเอ็นต์ Java HBase
คุณจะได้เรียนรู้วิธีการ
- หลีกเลี่ยงข้อผิดพลาดที่พบบ่อยด้วยการออกแบบสคีมา
- นำเข้าข้อมูลในไฟล์ลำดับ
- ค้นหาข้อมูล
เมื่อดำเนินการเสร็จแล้ว คุณจะมีแผนที่หลายแผนที่ที่แสดงข้อมูลรถประจำทางในนิวยอร์กซิตี้ ตัวอย่างเช่น คุณจะสร้างแผนที่ความนิยมของการเดินทางด้วยรถประจำทางในแมนฮัตตัน:
คุณจะให้คะแนนความพึงพอใจสำหรับประสบการณ์ในการใช้ 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" ที่มุมบนขวา
ตั้งค่าตัวแปรสภาพแวดล้อมต่อไปนี้เพื่อให้คัดลอกและวางคำสั่ง 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 นี้มีการแสดงข้อมูลผ่านภาพสำหรับแต่ละขั้นตอน หากคุณเพียงแค่ต้องการทำตาม ผลลัพธ์ของคำค้นหาแรกมีดังนี้
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
แอป Map Maker สามารถแสดงรายการหลายรายการในครั้งเดียว คุณจึงสามารถดูได้ว่ารถบัสคันไหนเป็นยานพาหนะจากข้อความค้นหาแรกที่คุณวิ่ง
การแก้ไขที่น่าสนใจสำหรับคำค้นหานี้คือการดูข้อมูลทั้งเดือนสำหรับสายรถประจำทาง 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 คุณสามารถดูแผนที่ความหนาแน่นของเส้นทางรถประจำทางได้ หยดน้ำสีส้มแสดงถึงจุดหยุด และหยดน้ำสีแดงสดคือจุดเริ่มต้นและจุดสิ้นสุดของเส้นทาง
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
รถประจำทางมุ่งหน้าไปทางตะวันออก
รถประจำทางกำลังมุ่งหน้าทิศตะวันตก
เมื่อเปรียบเทียบแผนที่ความหนาแน่น 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
11 ดำเนินการให้เสร็จสิ้น
ล้างข้อมูลเพื่อหลีกเลี่ยงการเรียกเก็บเงิน
คุณควรลบอินสแตนซ์เพื่อเลี่ยงไม่ให้เกิดการเรียกเก็บเงินกับบัญชี Google Cloud Platform สำหรับทรัพยากรที่ใช้ใน Codelab นี้
gcloud bigtable instances delete $INSTANCE_ID
หัวข้อที่ครอบคลุม
- การออกแบบสคีมา
- การตั้งค่าอินสแตนซ์ ตาราง และครอบครัว
- การนำเข้าไฟล์ลำดับด้วยโฟลว์ข้อมูล
- การค้นหาด้วยการค้นหา การสแกน การสแกนด้วยตัวกรอง และการสแกนแบบหลายช่วง
ขั้นตอนถัดไป
- ดูข้อมูลเพิ่มเติมเกี่ยวกับ Cloud Bigtable ในเอกสารประกอบ
- ลองใช้ฟีเจอร์อื่นๆ ของ Google Cloud Platform ด้วยตัวคุณเอง ดูวิดีโอบทแนะนำ
- ดูวิธีตรวจสอบข้อมูลอนุกรมเวลาด้วยการผสานรวม OpenTSDB