Checkpoint
Create a new dataset and table to store the data
/ 20
Execute the query to see how many unique products were viewed
/ 15
Execute the query to use the UNNEST() on array field
/ 15
Create a dataset and a table to ingest JSON data
/ 20
Execute the query to COUNT how many racers were there in total
/ 10
Execute the query that will list the total race time for racers whose names begin with R
/ 10
Execute the query to see which runner ran fastest lap time
/ 10
Bekerja dengan JSON, Array, dan Struct di BigQuery
- GSP416
- Ringkasan
- Penyiapan dan persyaratan
- Tugas 1. Membuat set data baru untuk menyimpan tabel
- Tugas 2. Berlatih bekerja dengan array di SQL
- Tugas 3. Membuat array Anda sendiri dengan ARRAY_AGG()
- Tugas 4. Membuat kueri tabel yang berisi array
- Tugas 5. Pengantar STRUCT
- Tugas 6. Berlatih dengan STRUCT dan array
- Tugas 7. Pertanyaan lab: STRUCT()
- Tugas 8. Pertanyaan lab: Membuka array dengan UNNEST( )
- Tugas 9. Memfilter dalam nilai array
- Selamat!
GSP416
Ringkasan
BigQuery adalah database analisis berbiaya rendah dan NoOps yang dikelola sepenuhnya oleh Google. Dengan BigQuery, Anda dapat membuat kueri data berskala terabyte tanpa harus memiliki administrator database atau infrastruktur apa pun untuk mengelolanya. BigQuery menggunakan SQL dan dapat memanfaatkan model bayar sesuai penggunaan. Dengan BigQuery, Anda dapat berfokus menganalisis data untuk menemukan insight yang bermakna.
Di lab ini, Anda akan bekerja secara mendalam dengan data semi-terstruktur (menyerap jenis data JSON, Array) di dalam BigQuery. Mendenormalisasi skema Anda menjadi satu tabel dengan kolom berulang dan bertingkat dapat meningkatkan performa, namun sintaksis SQL untuk bekerja dengan data array bisa jadi rumit. Anda akan berlatih memuat, membuat kueri, memecahkan masalah, dan menghapus tingkatan berbagai set data semi-terstruktur.
Yang akan Anda lakukan
Di lab ini, Anda akan mempelajari cara:
- Memuat dan membuat kueri data semi-terstruktur termasuk menghapus tingkatan.
- Memecahkan masalah kueri pada data semi-terstruktur.
Penyiapan dan persyaratan
Sebelum mengklik tombol Mulai Lab
Baca petunjuk ini. Lab memiliki timer dan Anda tidak dapat menjedanya. Timer, yang dimulai saat Anda mengklik Start Lab, akan menampilkan durasi ketersediaan resource Google Cloud untuk Anda.
Lab praktik ini dapat Anda gunakan untuk melakukan sendiri aktivitas lab di lingkungan cloud sungguhan, bukan di lingkungan demo atau simulasi. Untuk mengakses lab ini, Anda akan diberi kredensial baru yang bersifat sementara dan dapat digunakan untuk login serta mengakses Google Cloud selama durasi lab.
Untuk menyelesaikan lab ini, Anda memerlukan:
- Akses ke browser internet standar (disarankan browser Chrome).
- Waktu untuk menyelesaikan lab. Ingat, setelah dimulai, lab tidak dapat dijeda.
Cara memulai lab dan login ke Google Cloud Console
-
Klik tombol Start Lab. Jika Anda perlu membayar lab, jendela pop-up akan terbuka untuk memilih metode pembayaran. Di sebelah kiri adalah panel Lab Details dengan info berikut:
- Tombol Open Google Cloud console
- Waktu tersisa
- Kredensial sementara yang harus Anda gunakan untuk lab ini
- Informasi lain, jika diperlukan, untuk menyelesaikan lab ini
-
Klik Open Google Cloud console (atau klik kanan dan pilih Open Link in Incognito Window jika Anda menjalankan browser Chrome).
Lab akan menjalankan resource, lalu membuka tab lain yang menampilkan halaman Sign in.
Tips: Atur tab di jendela terpisah secara berdampingan.
Catatan: Jika Anda melihat dialog Choose an account, klik Use Another Account. -
Jika perlu, salin Username di bawah dan tempel ke dialog Sign in.
{{{user_0.username | "Username"}}} Anda juga dapat menemukan Username di panel Lab Details.
-
Klik Next.
-
Salin Password di bawah dan tempel ke dialog Welcome.
{{{user_0.password | "Password"}}} Anda juga dapat menemukan Password di panel Lab Details.
-
Klik Next.
Penting: Anda harus menggunakan kredensial yang diberikan lab. Jangan menggunakan kredensial akun Google Cloud Anda. Catatan: Menggunakan akun Google Cloud sendiri untuk lab ini dapat dikenai biaya tambahan. -
Klik halaman berikutnya:
- Setujui persyaratan dan ketentuan.
- Jangan tambahkan opsi pemulihan atau autentikasi 2 langkah (karena ini akun sementara).
- Jangan mendaftar uji coba gratis.
Setelah beberapa saat, Konsol Google Cloud akan terbuka di tab ini.
Membuka konsol BigQuery
- Di Google Cloud Console, pilih Navigation menu > BigQuery.
Kotak pesan Welcome to BigQuery in the Cloud Console akan terbuka. Kotak pesan ini menyediakan link ke panduan memulai dan catatan rilis.
- Klik Done.
Konsol BigQuery terbuka.
Tugas 1. Membuat set data baru untuk menyimpan tabel
- Di BigQuery Anda, klik tiga titik di samping Project ID Anda dan pilih Create dataset:
-
Namai set data baru ini dengan
fruit_store
. Gunakan nilai default untuk opsi lainnya (Data Location, Default Expiration). -
Klik Create dataset.
Tugas 2. Berlatih bekerja dengan array di SQL
Di SQL, biasanya Anda akan memiliki satu nilai untuk tiap baris seperti daftar buah di bawah ini:
Baris |
Buah |
1 |
rasberi |
2 |
beri hitam |
3 |
stroberi |
4 |
ceri |
Bagaimana jika Anda menginginkan daftar item buah untuk tiap orang di toko? Daftarnya bisa tampak seperti berikut:
Baris |
Buah |
Orang |
1 |
rasberi |
santi |
2 |
beri hitam |
santi |
3 |
stroberi |
santi |
4 |
ceri |
santi |
5 |
jeruk |
feri |
6 |
apel |
feri |
Dalam SQL database relasional tradisional, Anda akan melihat pengulangan nama dan langsung berpikir untuk membagi tabel di atas menjadi dua tabel terpisah: Item Buah dan Orang. Proses ini disebut normalisasi (beralih dari satu tabel ke banyak tabel). Normalisasi adalah pendekatan umum untuk database transaksional seperti mySQL.
Untuk data warehousing, analis data sering kali melakukannya dengan arah sebaliknya (denormalisasi) dan menyatukan banyak tabel terpisah ke dalam satu tabel pelaporan besar.
Sekarang, Anda akan mempelajari pendekatan berbeda yang menyimpan data pada tingkat perincian berbeda, semuanya dalam satu tabel menggunakan kolom berulang:
Baris |
Buah (array) |
Orang |
1 |
rasberi |
santi |
beri hitam | ||
stroberi | ||
ceri | ||
2 |
jeruk |
feri |
apel |
Apa yang aneh pada tabel sebelumnya?
- Hanya terdiri atas dua baris.
- Ada banyak nilai kolom untuk Buah dalam satu baris.
- Orang-orang dikaitkan dengan semua nilai kolom.
Apa insight utamanya? Jenis data array
.
Cara yang lebih mudah untuk menafsirkan array Buah:
Baris |
Buah (array) |
Orang |
1 |
[rasberi, beri hitam, stroberi, ceri] |
santi |
2 |
[jeruk, apel] |
feri |
Kedua tabel ini sama persis. Ada dua pembelajaran utama di sini:
- Array adalah daftar item dalam tanda kurung [ ]
- BigQuery secara visual menampilkan array secara flattened. BigQuery mencantumkan nilai dalam array secara vertikal (perhatikan bahwa semua nilai tersebut masih termasuk dalam satu baris)
Cobalah sendiri.
- Masukkan kode berikut dalam Editor Kueri BigQuery:
-
Klik Run.
-
Sekarang coba jalankan yang ini:
Anda akan mendapatkan error seperti berikut:
Error: Array elements of types {INT64, STRING} do not have a common supertype at [3:1]
Array hanya dapat berbagi satu tipe data (semua string, semua angka).
- Berikut tabel akhir untuk diterapkan kueri:
-
Klik Run.
-
Setelah melihat hasilnya, klik tab JSON untuk melihat struktur hasil yang disusun bertingkat.
Memuat JSON semi-terstruktur ke BigQuery
Bagaimana jika Anda memiliki file JSON yang perlu diserap ke BigQuery?
Buat tabel baru fruit_details
dalam set data.
- Klik set data
fruit_store
.
Sekarang Anda akan melihat opsi Create Table.
- Tambahkan detail berikut untuk tabel:
- Source: Pilih Google Cloud Storage dalam dropdown Create table from.
-
Pilih file dari bucket Cloud Storage:
cloud-training/data-insights-course/labs/optimizing-for-performance/shopping_cart.json
- Format file: JSONL (Newline delimited JSON)
-
Namai tabel baru tersebut dengan
fruit_details
. -
Centang kotak centang Schema (Auto detect).
-
Klik Create table.
Dalam skema, perhatikan bahwa fruit_array
ditandai sebagai REPEATED yang berarti ia adalah sebuah array.
Rangkuman
- BigQuery secara native mendukung array
- Nilai array harus memiliki jenis data yang sama
- Array disebut kolom REPEATED di BigQuery
Klik Check my progress untuk memverifikasi tujuan.
Tugas 3. Membuat array Anda sendiri dengan ARRAY_AGG()
Belum ada array di tabel Anda? Anda bisa membuatnya.
- Salin dan tempel kueri di bawah ini untuk menjelajahi set data publik ini:
- Klik Run dan lihat hasilnya.
Sekarang, gunakan fungsi ARRAY_AGG()
untuk menggabungkan nilai string kita ke dalam array.
- Salin dan tempel kueri di bawah ini untuk menjelajahi set data publik ini:
- Klik Run dan lihat hasilnya.
- Selanjutnya, gunakan fungsi
ARRAY_LENGTH()
untuk menghitung jumlah halaman dan produk yang dilihat:
- Selanjutnya, hapus duplikat halaman dan produk sehingga Anda dapat melihat berapa banyak produk unik yang ditampilkan dengan menambahkan
DISTINCT
keARRAY_AGG()
:
Klik Check my progress untuk memverifikasi tujuan.
Rangkuman
Anda dapat melakukan beberapa hal yang cukup berguna dengan array seperti:
- mencari jumlah elemen dengan
ARRAY_LENGTH(<array>)
- menghapus duplikat elemen dengan
ARRAY_AGG(DISTINCT <field>)
- mengurutkan elemen dengan
ARRAY_AGG(<field> ORDER BY <field>)
- membatasi
ARRAY_AGG(<field> LIMIT 5)
Tugas 4. Membuat kueri tabel yang berisi array
Set Data Publik BigQuery untuk Google Analytics bigquery-public-data.google_analytics_sample
memiliki lebih banyak kolom dan baris daripada set data kursus kita data-to-insights.ecommerce.all_sessions
. Lebih penting lagi, set data ini sudah menyimpan nilai kolom seperti produk, halaman, dan transaksi secara native sebagai ARRAY.
- Salin dan tempel kueri di bawah ini untuk menjelajahi data yang tersedia dan melihat apakah Anda dapat menemukan kolom dengan nilai berulang (array) atau tidak:
-
Jalankan kueri
-
Scroll ke kanan dalam hasil hingga Anda melihat kolom
hits.product.v2ProductName
(alias multikolom akan segera dibahas).
Jumlah kolom yang tersedia dalam skema Google Analytics bisa sangat banyak untuk dianalisis.
- Cobalah untuk membuat kueri hanya untuk kolom kunjungan dan nama halaman seperti sebelumnya:
Anda akan mendapatkan error:
Error:Cannot access field page on a value with type ARRAY<STRUCT<hitNumber INT64, time INT64, hour INT64, ...>> at [3:8]
Sebelum Anda dapat membuat kueri kolom REPEATED (array) secara normal, Anda harus terlebih dahulu memecah array kembali menjadi baris.
Misalnya, array untuk hits.page.pageTitle
saat ini disimpan sebagai satu baris seperti:
dan array tersebut harus menjadi:
Bagaimana cara melakukannya dengan SQL?
Jawaban: Gunakan fungsi UNNEST() pada kolom array Anda:
Kita akan membahas UNNEST() secara lebih mendetail nanti, tetapi untuk saat ini ketahuilah bahwa:
- Anda perlu menggunakan fungsi UNNEST() pada array untuk mengembalikan elemen array ke dalam baris
- UNNEST() selalu mengikuti nama tabel dalam klausa FROM Anda (anggaplah secara konseptual seperti tabel yang telah digabungkan sebelumnya)
Klik Check my progress untuk memverifikasi tujuan.
Tugas 5. Pengantar STRUCT
Anda mungkin bertanya-tanya mengapa alias kolom hit.page.pageTitle
terlihat seperti tiga kolom dalam satu kolom yang dipisahkan oleh titik. Sama seperti nilai ARRAY yang memberi Anda fleksibilitas untuk mendalami perincian kolom Anda, jenis data lain memungkinkan Anda memperluas skema dengan mengelompokkan kolom terkait bersama-sama. Jenis data SQL tersebut adalah jenis data STRUCT.
Cara termudah untuk memikirkan STRUCT adalah dengan menganggapnya secara konseptual seperti tabel terpisah yang sudah digabungkan sebelumnya ke dalam tabel utama Anda.
STRUCT dapat memiliki:
- Satu atau banyak kolom di dalamnya
- Jenis data yang sama atau berbeda untuk tiap kolom
- Aliasnya sendiri
Kedengarannya persis seperti tabel 'kan?
Menjelajahi set data dengan STRUCT
-
Untuk membuka set data bigquery-public-data, klik +ADD lalu pilih Star a project by name dan masukkan nama
bigquery-public-data
-
Klik Star.
Project bigquery-public-data
tercantum di bagian Explorer.
-
Buka bigquery-public-data.
-
Cari dan buka set data google_analytics_sample.
-
Klik tabel ga_sessions(366)_.
-
Mulailah men-scroll skema dan jawab pertanyaan berikut dengan menggunakan fitur cari di browser Anda.
Seperti yang dapat Anda bayangkan, ada banyak sekali data sesi situs yang disimpan untuk situs e-commerce modern.
Keuntungan utama memiliki 32 STRUCT dalam satu tabel adalah Anda dapat menjalankan kueri seperti ini tanpa harus melakukan JOIN apa pun:
.*
memberi tahu BigQuery untuk menampilkan semua kolom untuk STRUCT tersebut (seperti jika totals.*
adalah tabel terpisah yang menjadi dasar penggabungan).Dengan menyimpan tabel pelaporan besar sebagai STRUCT ("tabel" yang telah digabungkan sebelumnya) dan ARRAY (perincian mendalam), Anda akan:
- Mendapatkan keunggulan performa yang signifikan dengan menghindari JOIN 32 tabel
- Mendapatkan data terperinci dari ARRAY saat Anda memerlukannya. Jika Anda tidak membutuhkannya pun tidak apa-apa karena BigQuery akan menyimpan tiap kolom satu per satu di disk.
- Mendapatkan semua konteks bisnis dalam satu tabel, sehingga Anda tidak perlu mengkhawatirkan kunci untuk JOIN dan tabel mana yang memiliki data yang Anda perlukan
Tugas 6. Berlatih dengan STRUCT dan array
Set data berikutnya adalah waktu putaran pelari di lintasan. Tiap putaran akan disebut "split".
- Dengan kueri ini, coba gunakan sintaksis STRUCT dan perhatikan berbagai jenis kolom dalam container struct:
Baris |
runner.name |
runner.split |
1 |
Rudisha |
23,4 |
Apa yang Anda perhatikan terkait alias kolom? Karena ada kolom yang tersusun bertingkat di dalam struct (name dan split adalah subset dari runner), Anda akan mendapatkan notasi titik.
Bagaimana jika pelari memiliki beberapa waktu split untuk sekali lomba (seperti waktu per putaran)?
Tentu saja dengan array!
- Jalankan kueri di bawah ini untuk mengonfirmasi:
Baris |
runner.name |
runner.splits |
1 |
Rudisha |
23,4 |
26,3 | ||
26,4 | ||
26,1 |
Ringkasnya:
- Struct adalah container yang dapat memiliki beberapa nama kolom dan jenis data yang tersusun bertingkat di dalamnya.
- Array dapat menjadi salah satu jenis kolom di dalam Struct (seperti yang ditunjukkan di atas dengan kolom splits).
Berlatih menyerap data JSON
-
Buat set data baru bernama
racing
. -
Klik set data
racing
, lalu klik Create table.
- Source: pilih Google Cloud Storage pada dropdown Create table from.
-
Pilih file dari bucket Cloud Storage:
cloud-training/data-insights-course/labs/optimizing-for-performance/race_results.json
- Format file: JSONL (Newline delimited JSON)
- Pada Schema, klik penggeser Edit as text dan tambahkan kode berikut:
-
Namai tabel baru tersebut dengan
race_results
. -
Klik Create table.
-
Setelah pekerjaan pemuatan berhasil, pratinjau skema untuk tabel yang baru dibuat:
Kolom manakah yang merupakan STRUCT? Bagaimana Anda mengetahuinya?
Kolom participants adalah STRUCT karena jenisnya RECORD.
Kolom manakah yang merupakan ARRAY?
Kolom participants.splits
adalah array float di dalam struct participants
induk. Kolom ini memiliki mode REPEATED yang menandakan array. Nilai array ini disebut nilai bertingkat karena merupakan beberapa nilai di dalam satu kolom.
Klik Check my progress untuk memverifikasi tujuan.
Berlatih membuat kueri kolom berulang dan bertingkat
- Mari kita lihat semua pelari untuk lomba 800 Meter:
Berapa banyak baris yang ditampilkan?
Jawaban: 1
Bagaimana jika Anda ingin mencantumkan nama masing-masing pelari dan jenis lombanya?
- Jalankan skema di bawah ini dan lihat apa yang terjadi:
Error: Cannot access field name on a value with type ARRAY<STRUCT<name STRING, splits ARRAY<FLOAT64>>>> at [2:27]
Sama seperti jika Anda lupa menggunakan GROUP BY saat Anda memakai fungsi agregasi, di sini ada dua tingkat perincian yang berbeda. Satu baris untuk lomba dan tiga baris untuk nama peserta. Jadi bagaimana cara mengubah yang berikut...
Baris |
race |
participants.name |
1 |
800M |
Rudisha |
2 |
??? |
Makhloufi |
3 |
??? |
Murphy |
...menjadi berikut:
Baris |
race |
participants.name |
1 |
800M |
Rudisha |
2 |
800M |
Makhloufi |
3 |
800M |
Murphy |
Dalam SQL relasional tradisional, jika Anda memiliki tabel lomba dan tabel peserta, apa yang akan Anda lakukan untuk mendapatkan informasi dari kedua tabel tersebut? Anda akan menggabungkan keduanya menggunakan fungsi JOIN. Di sini, STRUCT peserta (yang secara konseptual sangat mirip dengan tabel) sudah menjadi bagian dari tabel race Anda, tetapi belum berkorelasi secara benar dengan kolom "race" yang non-STRUCT.
Dapatkah Anda memikirkan perintah SQL yang berisi dua kata yang akan Anda gunakan untuk mengorelasikan lomba 800M dengan masing-masing pelari di tabel pertama?
Jawaban: CROSS JOIN
Bagus.
- Sekarang coba jalankan ini:
Table name "participants" missing dataset while no default dataset is set in the request
.
Meskipun STRUCT peserta terlihat seperti sebuah tabel, namun secara teknis masih merupakan sebuah kolom di tabel racing.race_results
.
- Tambahkan nama set data ke kueri:
- Lalu klik Run.
Wow! Anda berhasil membuat daftar semua pelari untuk tiap lomba!
Baris |
race |
name |
1 |
800M |
Rudisha |
2 |
800M |
Makhloufi |
3 |
800M |
Murphy |
4 |
800M |
Bosse |
5 |
800M |
Rotich |
6 |
800M |
Lewandowski |
7 |
800M |
Kipketer |
8 |
800M |
Berian |
- Anda dapat menyederhanakan kueri terakhir dengan:
- Menambahkan alias untuk tabel asli
- Mengganti kata “CROSS JOIN” dengan koma (tanda koma secara implisit melakukan cross join)
Tindakan ini akan memberi Anda hasil kueri yang sama:
Jika ada lebih dari satu jenis lomba (800M, 100M, 200M), bukankah CROSS JOIN hanya akan menghubungkan tiap nama pelari dengan tiap kemungkinan lomba seperti Cartesian product?
Jawaban: Tidak. Ini adalah cross join terkorelasi yang hanya membuka elemen yang terkait dengan satu baris. Untuk mendapatkan info lebih lanjut, baca bagian bekerja dengan ARRAY dan STRUCT
Rangkuman STRUCT:
-
STRUCT SQL hanyalah sebuah container kolom data lain yang dapat memiliki jenis data berbeda. Kata struct berarti struktur data. Ingat contoh sebelumnya:
STRUCT(``"Rudisha" as name, [23.4, 26.3, 26.4, 26.1] as splits``)`` AS runner
- STRUCT diberi alias (seperti runner di atas) dan secara konseptual dapat dianggap sebagai tabel di dalam tabel utama Anda.
- STRUCT (dan ARRAY) harus dibuka sebelum Anda dapat mengoperasikan elemennya. Gunakan fungsi UNNEST() pada nama struct itu sendiri atau kolom struct yang berupa array untuk membuka dan meratakannya ke format yang mudah dibaca.
Tugas 7. Pertanyaan lab: STRUCT()
Jawab pertanyaan di bawah ini menggunakan tabel racing.race_results
yang Anda buat sebelumnya.
Tugas: Tulis kueri untuk menghitung jumlah total pelari yang ada di tabel menggunakan fungsi COUNT.
- Untuk memulai, gunakan kueri yang sudah ditulis sebagian di bawah ini:
FROM
.Solusi yang dapat dilakukan:
Baris |
racer_count |
1 |
8 |
Jawaban: Ada 8 orang pelari yang mengikuti lomba tersebut.
Klik Check my progress untuk memverifikasi tujuan.
Tugas 8. Pertanyaan lab: Membuka array dengan UNNEST( )
Tulis kueri yang akan mencantumkan total waktu lomba untuk pelari yang namanya dimulai dengan huruf R. Urutkan hasilnya dengan total waktu tercepat terlebih dahulu. Gunakan operator UNNEST() dan mulai dengan kueri yang sudah ditulis sebagian di bawah ini.
- Lengkapi kueri:
- Anda perlu membuka struct dan array di dalam struct sebagai sumber data setelah klausa FROM Anda.
- Pastikan untuk menggunakan alias jika diperlukan.
Solusi yang dapat dilakukan:
Baris |
name |
total_race_time |
1 |
Rudisha |
102.19999999999999 |
2 |
Rotich |
103.6 |
Klik Check my progress untuk memverifikasi tujuan.
Tugas 9. Memfilter dalam nilai array
Anda kebetulan melihat bahwa waktu putaran tercepat yang tercatat untuk lomba lari 800 M adalah 23,2 detik, tetapi Anda tidak melihat pelari mana yang berlari pada putaran tersebut. Buat kueri yang menampilkan hasil tersebut.
- Selesaikan kueri yang sudah ditulis sebagian:
Solusi yang dapat dilakukan:
Baris |
name |
split_time |
1 |
Kipketer |
23,2 |
Klik Check my progress untuk memverifikasi tujuan.
Selamat!
Anda telah berhasil menyerap set data JSON, membuat ARRAY dan STRUCT, serta menghapus tingkatan data semi-terstruktur untuk mendapatkan insight.
Langkah berikutnya/Pelajari lebih lanjut
- Untuk mendapatkan info lebih lanjut, baca bagian Bekerja dengan Array.
- Lihat lab ini:
Sertifikasi dan pelatihan Google Cloud
...membantu Anda mengoptimalkan teknologi Google Cloud. Kelas kami mencakup keterampilan teknis dan praktik terbaik untuk membantu Anda memahami dengan cepat dan melanjutkan proses pembelajaran. Kami menawarkan pelatihan tingkat dasar hingga lanjutan dengan opsi on demand, live, dan virtual untuk menyesuaikan dengan jadwal Anda yang sibuk. Sertifikasi membantu Anda memvalidasi dan membuktikan keterampilan serta keahlian Anda dalam teknologi Google Cloud.
Manual Terakhir Diperbarui pada 03 Februari 2024
Lab terakhir diuji pada 25 Agustus 2023
Hak cipta 2024 Google LLC Semua hak dilindungi undang-undang. Google dan logo Google adalah merek dagang dari Google LLC. Semua nama perusahaan dan produk lain mungkin adalah merek dagang masing-masing perusahaan yang bersangkutan.