Mengoptimalkan performa BigQuery DataFrames

Anda dapat mengoptimalkan alur kerja BigQuery DataFrames untuk menganalisis dan mentransformasi data menggunakan API yang kompatibel dengan pandas, sekaligus menjaga waktu dan biaya eksekusi tetap rendah. Menerapkan teknik pengoptimalan tertentu, seperti mode pengurutan parsial dan caching hasil, memungkinkan Anda memproses data dengan lebih cepat dan hemat biaya.

Menggunakan mode pengurutan parsial

BigQuery DataFrames memiliki fitur mode pengurutan, yang menerapkan urutan baris tertentu untuk operasi seperti fungsi jendela dan join. Anda dapat menentukan mode pengurutan dengan menetapkan properti ordering_mode ke strict (dikenal sebagai mode pengurutan ketat, yang merupakan default) atau partial (dikenal sebagai mode pengurutan parsial). Menggunakan setelan partial dapat membuat kueri Anda lebih efisien.

Mode pengurutan parsial berbeda dengan mode pengurutan ketat. Mode pengurutan ketat mengatur semua baris dalam urutan tertentu. Pengurutan total ini membuat BigQuery DataFrames berfungsi lebih baik dengan pandas, sehingga Anda dapat mengakses baris berdasarkan urutannya menggunakan properti DataFrame.iloc. Namun, pengurutan total dan indeks berurutan default-nya mencegah filter pada kolom atau baris mengurangi jumlah data yang dipindai. Pencegahan ini terjadi kecuali jika Anda menerapkan filter tersebut sebagai parameter ke fungsi read_gbq dan read_gbq_table. Untuk mengurutkan semua baris dalam DataFrame, BigQuery DataFrames membuat hash dari semua baris. Operasi ini dapat menyebabkan pemindaian data lengkap yang mengabaikan filter baris dan kolom.

Mode pengurutan parsial menghentikan BigQuery DataFrames membuat pengurutan total untuk semua baris dan menonaktifkan fitur yang memerlukan pengurutan total, seperti properti DataFrame.iloc. Mode pengurutan parsial juga menetapkan class DefaultIndexKind ke indeks null, bukan ke indeks berurutan.

Saat Anda memfilter objek DataFrame menggunakan mode pengurutan parsial, BigQuery DataFrames tidak menghitung baris mana yang tidak ada dalam indeks berurutan. Mode pengurutan parsial juga tidak otomatis menggabungkan data berdasarkan indeks. Pendekatan ini dapat meningkatkan efisiensi kueri Anda. Namun, baik Anda menggunakan mode pengurutan ketat default atau mode pengurutan parsial, BigQuery DataFrames API berfungsi seperti API pandas yang sudah dikenal.

Dengan mode pengurutan parsial dan ketat, Anda membayar resource BigQuery yang Anda gunakan. Namun, menggunakan mode pengurutan parsial dapat menurunkan biaya saat bekerja dengan tabel berpartisi dan dikelompokkan yang besar. Pengurangan biaya ini terjadi karena filter baris pada kolom cluster dan partisi mengurangi jumlah pemrosesan data.

Mengaktifkan mode pengurutan parsial

Untuk menggunakan pengurutan parsial, tetapkan properti ordering_mode ke partial sebelum melakukan operasi lain dengan BigQuery DataFrames, seperti yang ditunjukkan dalam contoh kode berikut:

import bigframes.pandas as bpd

bpd.options.bigquery.ordering_mode = "partial"

Mode pengurutan parsial mencegah penggabungan implisit objek BigQuery DataFrames yang tidak terkait karena tidak memiliki indeks berurutan. Sebagai gantinya, Anda harus secara eksplisit memanggil metode DataFrame.merge untuk menggabungkan dua objek BigQuery DataFrames yang berasal dari ekspresi tabel yang berbeda.

Fitur Series.unique() dan Series.drop_duplicates() tidak berfungsi dengan mode pengurutan parsial. Sebagai gantinya, gunakan metode groupby untuk menemukan nilai unik, seperti yang ditunjukkan dalam contoh berikut:

# Avoid order dependency by using groupby instead of drop_duplicates.
unique_col = df.groupby(["column"], as_index=False).size().drop(columns="size")

Dengan mode pengurutan parsial, output fungsi DataFrame.head(n) dan Series.head(n) mungkin tidak sama setiap kali Anda menjalankannya. Untuk mendownload sampel data kecil yang acak, gunakan metode DataFrame.peek() atau Series.peek().

Untuk tutorial mendetail yang menggunakan properti ordering_mode = "partial", lihat Menganalisis download paket dari PyPI dengan BigQuery DataFrames.

Pemecahan masalah

Karena BigQuery DataFrames dalam mode pengurutan parsial terkadang tidak memiliki pengurutan atau indeks, Anda mungkin mengalami masalah berikut saat menggunakan beberapa metode yang kompatibel dengan pandas.

Error urutan diperlukan

Beberapa fitur, seperti fungsi DataFrame.head() dan DataFrame.iloc, memerlukan pengurutan. Untuk mengetahui daftar fitur yang memerlukan pengurutan, lihat kolom Requires ordering di Supported pandas APIs.

Jika objek tidak memiliki pengurutan, operasi akan gagal dengan pesan OrderRequiredError seperti berikut: OrderRequiredError: Op iloc requires an ordering. Use .sort_values or .sort_index to provide an ordering.

Seperti yang dinyatakan dalam pesan error, Anda dapat memberikan pengurutan menggunakan metode DataFrame.sort_values() untuk mengurutkan berdasarkan satu atau beberapa kolom. Metode lain, seperti DataFrame.groupby(), secara implisit memberikan pengurutan total berdasarkan kunci kelompokkan menurut.

Tidak seperti pandas, jika Anda berada dalam mode pengurutan parsial, menjalankan kode yang sama dapat memberikan hasil yang berbeda setiap kali Anda menjalankannya. Untuk memastikan hasil yang konsisten, gunakan pengurutan total yang stabil untuk semua baris.

Error indeks null

Beberapa fitur, seperti properti DataFrame.unstack() dan Series.interpolate(), memerlukan indeks. Untuk mengetahui daftar fitur yang memerlukan indeks, lihat kolom Requires index di Supported pandas APIs.

Saat Anda menggunakan operasi yang memerlukan indeks dengan mode pengurutan parsial, operasi tersebut akan memunculkan pesan NullIndexError seperti berikut: NullIndexError: DataFrame cannot perform interpolate as it has no index. Set an index using set_index.

Seperti yang dinyatakan dalam pesan error, Anda dapat memberikan indeks menggunakan metode DataFrame.set_index() untuk mengurutkan berdasarkan satu atau beberapa kolom. Metode lain, seperti DataFrame.groupby(), secara implisit menyediakan indeks berdasarkan kunci kelompokkan menurut, kecuali jika parameter as_index=False ditetapkan.

Menyimpan hasil ke dalam cache setelah operasi yang mahal

BigQuery DataFrames menyimpan operasi secara lokal dan menunda menjalankan kueri hingga kondisi tertentu terpenuhi. Hal ini dapat menyebabkan operasi yang sama berjalan beberapa kali di berbagai kueri.

Untuk menghindari pengulangan operasi yang mahal, simpan hasil sementara dengan metode cache(), seperti yang ditunjukkan dalam contoh berikut:

# Assume you have 3 large dataframes "users", "group" and "transactions"

# Expensive join operations
final_df = users.join(groups).join(transactions)
final_df.cache()
# Subsequent derived results will reuse the cached join
print(final_df.peek())
print(len(final_df[final_df["completed"]]))
print(final_df.groupby("group_id")["amount"].mean().peek(30))

Metode ini membuat tabel BigQuery sementara untuk menyimpan hasil Anda. Anda akan dikenai biaya untuk penyimpanan tabel sementara ini di BigQuery.

Melihat pratinjau data dengan metode peek()

BigQuery DataFrames menawarkan dua metode API untuk melihat pratinjau data:

  • peek(n) menampilkan n baris data, dengan n adalah jumlah baris.
  • head(n) menampilkan n baris data pertama, bergantung pada konteksnya, dengan n adalah jumlah baris.

Gunakan metode head() hanya jika urutan data penting, misalnya, saat Anda menginginkan lima nilai terbesar dalam sebuah kolom. Dalam kasus lain, gunakan metode peek() untuk pengambilan data yang lebih efisien, seperti yang ditunjukkan dalam contoh kode berikut:

import bigframes.pandas as bpd

# Read the "Penguins" table into a dataframe
df = bpd.read_gbq("bigquery-public-data.ml_datasets.penguins")

# Preview 3 random rows
df.peek(3)

Anda juga dapat menggunakan metode peek() untuk mendownload sampel data kecil yang acak saat menggunakan mode pengurutan parsial.

Menunda pengambilan data repr()

Anda dapat memanggil metode repr() di BigQuery DataFrames dengan notebook atau debugger IDE Anda. Panggilan ini memicu panggilan head() yang mengambil data sebenarnya. Pengambilan ini dapat memperlambat proses coding dan proses debug iteratif Anda, serta menimbulkan biaya.

Untuk mencegah metode repr() mengambil data, tetapkan atribut repr_mode ke "deferred", seperti yang ditunjukkan dalam contoh berikut:

import bigframes.pandas as bpd

bpd.options.display.repr_mode = "deferred"

Dalam mode tertunda, Anda hanya dapat melihat pratinjau data dengan panggilan peek() dan head() eksplisit.

Langkah berikutnya