Hadi gidelim.
Danışmaya ulaşan müşteriler için veri örnekleri hazırlamak üzere bir senaryo geliştiriyordum. Örneklerin her dosyada 100 satırı vardır ve bunlar 55 yerel ayara bölünmüştür. Sorgum şuna benziyor
SELECT * FROM `project.dataset.table` WHERE ts BETWEEN TIMESTAMP("2022-12-01") AND TIMESTAMP("2023-02-28") AND locale = "US" LIMIT 100;
Veriler "europe-west-4"te saklanıyordu ve sorgulamanın ücreti TB başına 6 ABD dolarıydı . Böylece betiği çalıştırarak şunu işledim:
Çok pahalı.
Komut dosyası JavaScript modüllerinde yazılmıştır.
// bq-samples.mjs import { BigQuery } from "@google-cloud/bigquery"; import { Parser } from "@json2csv/plainjs"; import makeDir from "make-dir"; import { write } from "./write.mjs"; import { locales } from "./locales.mjs"; import { perf } from "./performance.mjs"; const q = (locale, start, end, limit) => `SELECT * FROM \`project.dataset.table\` WHERE ts BETWEEN TIMESTAMP("2022-12-01") AND TIMESTAMP("2023-02-28") AND locale = "${locale}" LIMIT ${limit}` async function main() { const timer = perf() const dir = await makeDir('samples') const bigquery = new BigQuery() const csvParser = new Parser({}) try { const jobs = locales.map((locale) => async () => { // get query result from BigQuery const [job] = await bigquery.createQueryJob({ query: q(locale, "2022-12-01", "2023-02-28", 100), }) const [rows] = await job.getQueryResults() // parse rows into csv format const csv = parse(csvParser, rows) // write data into csv files and store in the file system await write(csv, dir, locale, "2022-12-01", "2023-02-28", 100) }) await Promise.all(jobs.map((job) => job())) console.log(`✨ Done in ${timer.stop()} seconds.`) } catch (error) { console.error('❌ Failed to create sample file', error) } } await main()
Yerel ayar başına CSV formatında bir örnek dosya oluşturur. Süreç basittir:
Sorgumda birkaç şeyi yanlış yaptığım ortaya çıktı. Fiyatlandırma modeline tekrar bakarsanız maliyetin yalnızca ne kadar veri işlediğinizle ilgili olduğunu fark edeceksiniz. Dolayısıyla sorgumun 100 satır üretemeyecek kadar fazla veri aradığı açık.
Bu öngörüyle sorguyu adım adım optimize edelim.
Bu biraz mantığa aykırı. Select ifademin neden işlediği veri miktarıyla bir ilgisi var? Seçtiğim sütunlar ne olursa olsun aynı kaynaklardan ve verilerden okuyor olmalıyım değil mi?
Bu yalnızca satır odaklı veritabanları için geçerlidir.
BigQuery aslında sütunlu bir veritabanıdır . Sütun odaklıdır, yani veriler sütunlar halinde yapılandırılmıştır. BigQuery, temel bilgi işlem motoru olarak Dremel'i kullanıyor. Dremel'de veriler soğuk depodan aktif depoya taşındığında verileri bir ağaç yapısında saklar.
Her yaprak düğümü Protobuf formatında sütun odaklı bir “kayıttır”.
BigQuery'de her düğüm bir sanal makinedir. Bir sorgu yürütme, seçilen sütunları almak için kök sunucudan (düğüm) ara sunucular aracılığıyla yaprak sunuculara yayılır.
Tek tek sütunları seçmek için sorguyu değiştirebiliriz:
SELECT session_info_1, session_info_2, session_info_3, user_info_1, user_info_2, user_info_3, query_info_1, query_info_2, query_info_3, impression_info_1, impression_info_2, impression_info_3, ts FROM `project.dataset.table` WHERE ts BETWEEN TIMESTAMP("2022-12-01") AND TIMESTAMP("2023-02-28") AND locale = "US" LIMIT 100;
Tüm sütunları açıkça seçerek işlenen veriyi 3,08 TB'tan 2,94 TB'a düşürmeyi başardım. Bu 100 GB'lık bir azalmadır .
Google Cloud, tabloları tarihe göre bölümlememizi önerir. Verilerin yalnızca bir alt kümesini sorgulamamıza olanak tanır.
Sorguyu daha da optimize etmek için, tablo “ts” sütununa göre bölümlendiğinden, Where ifadesindeki tarih aralığını daraltabiliriz.
SELECT session_info_1, session_info_2, session_info_3, user_info_1, user_info_2, user_info_3, query_info_1, query_info_2, query_info_3, impression_info_1, impression_info_2, impression_info_3, ts FROM `project.dataset.table` WHERE ts = TIMESTAMP("2022-12-01") AND locale = "US" LIMIT 100;
Tarih aralığını üç ay yerine bir güne kadar daralttım. İşlenen veriyi 37.43 GB'a kadar indirmeyi başardım. Bu orijinal sorgunun sadece bir kısmı.
Maliyetleri azaltmanın başka bir yolu da sorgulama yaptığınız veri kümesini azaltmaktır. BigQuery, sorgu sonuçlarını daha küçük veri kümeleri halinde depolamak için hedef tablolar sunar. Hedef tabloları iki şekilde gelir: geçici ve kalıcı.
Geçici tabloların bir ömrü olduğundan ve paylaşılmak ve sorgulanmak üzere tasarlanmadığından, sorgu sonucunu gerçekleştirmek için kalıcı bir hedef tablo oluşturdum:
// bq-samples.mjs const dataset = bigquery.dataset('materialized_dataset') const materialzedTable = dataset.table('materialized_table') // ... const [job] = await bigquery.createQueryJob({ query: q(locale, '2022-12-01', '2023-02-28', 100), destination: materialzedTable, })
Sorgu sonuçları hedef tabloda saklanacaktır. Gelecekteki sorgular için referans görevi görecektir. Hedef tablodan sorgulama mümkün olduğunda BigQuery, tablodaki verileri işler. Aradığımız veri boyutunu büyük ölçüde azaltacaktır.
BigQuery'de maliyeti düşürmeye yönelik çok ilginç bir çalışma. Yalnızca üç kolay adımla:
İşlenen veri boyutunu 3 TB'tan 37,5 GB'a düşürmeyi başardım. Toplam maliyeti önemli ölçüde 3.000 $'dan 30 $'a düşürür.
BigQuery mimarisi hakkında daha fazla bilgi edinmek istiyorsanız bana yardımcı olan referansları burada bulabilirsiniz:
BigQuery maliyet optimizasyonları hakkında daha fazla bilgiyi Google Cloud belgelerinde bulabilirsiniz.
Örnek olayda benimle işbirliği yaptığı ve BigQuery mimarisini anlamama yardımcı olan değerli bilgiler sağladığı için Abu Nashir'e özellikle teşekkür ederim.
Bağlanmak mı istiyorsunuz?
Bu makale ilk olarak Daw-Chih'in web sitesinde yayınlanmıştır.