7 poin oleh GN⁺ 2024-09-26 | 2 komentar | Bagikan ke WhatsApp
  • Ini adalah daftar kebiasaan penulisan SQL dan pola kueri yang sering dipakai dalam pekerjaan analisis data, dengan catatan bahwa semuanya mungkin tidak berlaku sama di semua RDBMS
  • Dari sisi keterbacaan, disarankan memakai koma di awal, WHERE 1=1, indentasi, CTE, komentar, dan USING agar kueri lebih mudah dibaca dan diubah
  • Untuk pemrosesan data, contoh mencakup sintaks yang dipakai dalam praktik untuk memfilter hasil, membuat total, dan memeriksa perbedaan tabel, seperti anti-join, QUALIFY, GROUP BY ROLLUP, dan EXCEPT
  • Dari sisi performa dan akurasi, NOT IN yang bercampur NULL, konversi tipe implisit, serta konflik alias pada field hasil kalkulasi dapat memengaruhi hasil kueri atau kecepatannya
  • Dalam kueri yang kompleks, kebiasaan dasar seperti memahami urutan eksekusi, memeriksa dokumentasi, memperjelas asal kolom, dan memberi nama kueri tersimpan berperan penting untuk meningkatkan debugging dan reusability

Kebiasaan untuk Meningkatkan Keterbacaan Penulisan SQL

  • Repositori ini adalah daftar tips dan trik SQL yang dikumpulkan selama bertahun-tahun, berfokus pada hal-hal yang berguna dalam pekerjaan sehari-hari analis data dan hal-hal yang seandainya diketahui saat pertama kali menulis SQL
  • Beberapa tips mungkin tidak cocok untuk semua RDBMS
  • Koma di awal dan AND di awal

    • Untuk memisahkan field pada klausa SELECT, disarankan memakai koma di awal daripada koma di akhir
    • Ini membuat lebih jelas apakah sesuatu adalah kolom baru atau kode yang hanya pindah baris
    • Lebih mudah menemukan koma yang hilang meski panjang baris berbeda-beda
    • Dengan alasan yang sama, AND juga bisa diletakkan di awal sebelum kondisi dalam klausa WHERE
  • Mempermudah pengujian kondisi dengan WHERE 1=1

    • Jika menambahkan kondisi dummy 1=1 ke klausa WHERE, kueri tidak rusak meski kondisi dikomentari saat pengujian
    • Bahkan jika semua kondisi dikomentari, 1=1 tetap tersisa sehingga kueri masih dapat dijalankan
  • Indentasi dan formatter

    • Indentasi membantu rekan kerja dan diri Anda di masa depan membaca kueri dengan lebih mudah
    • Jika ada panduan tim atau perusahaan, ikutilah; jika tidak ada, sebaiknya gunakan gaya yang paling cocok untuk Anda
    • Anda dapat menggunakan formatter online poorsql atau linter sqlfluff
  • Pertimbangkan CTE untuk kueri kompleks

    • Jika inline view ditumpuk lebih dari 2–3 tingkat, kueri mudah menjadi sulit dipahami saat dilihat lagi beberapa minggu kemudian
    • CTE disajikan sebagai cara untuk membuat kueri panjang menjadi lebih terstruktur, sekaligus membantu reusability dan debugging
  • Komentar harus menjelaskan “mengapa”

    • Setelah waktu berlalu, bisa jadi sulit mengingat mengapa pemrosesan tertentu dilakukan
    • Secara umum, komentar sebaiknya menjelaskan mengapa sesuatu dilakukan, bukan bagaimana kode bekerja
    • Contohnya adalah menambahkan komentar pada kondisi yang mengecualikan konten archive karena CMS baru tidak dapat menangani format video archive
  • Gunakan USING untuk join kolom bernama sama

    • Saat melakukan join pada dua tabel menggunakan kolom dengan nama yang sama, USING dapat mengekspresikan join dengan lebih ringkas daripada ON
    • USING menghapus duplikasi kolom umum dari hasil dan hanya mengembalikan satu kolom
    • Jika menggunakan ON dan tidak menyebutkan kolom umum secara eksplisit, dapat terjadi error ambiguous column name

Sintaks yang Berguna untuk Pemrosesan Data

  • Menemukan baris yang tidak ada di tabel lain dengan anti-join

    • Anti-join digunakan untuk mengembalikan baris yang ada di satu tabel tetapi tidak memiliki pasangan di tabel lain
    • Contohnya membahas situasi mengambil hanya video_id dari konten yang tidak di-archive
    • Ada beberapa cara implementasi
    • Melakukan LEFT JOIN, lalu memfilter hanya baris dengan key dari tabel pasangan bernilai NULL
    • Menggunakan NOT IN dan subkueri
    • Menggunakan NOT EXISTS dan subkueri terkorelasi
    • NOT IN tidak disarankan karena dapat tidak bekerja sesuai harapan akibat nilai NULL
  • Memfilter hasil window function dengan QUALIFY

    • QUALIFY memungkinkan hasil kueri difilter berdasarkan hasil window function
    • Karena bisa memfilter tanpa inline view, jumlah baris kode dapat dikurangi
    • Contohnya memilih 10 pasar teratas per produk dengan DENSE_RANK(), lalu memfilternya dengan QUALIFY
    • Ada batasan bahwa QUALIFY tampaknya hanya tersedia di data warehouse besar seperti Snowflake, Amazon Redshift, dan Google BigQuery
  • GROUP BY dan ORDER BY berbasis posisi kolom

    • Alih-alih nama kolom, Anda bisa menulis berdasarkan posisi kolom seperti GROUP BY 1 dan ORDER BY 2
    • Ini bisa berguna untuk kueri sementara atau sekali pakai
    • Untuk kode produksi, disarankan selalu merujuk langsung ke nama kolom
  • Membuat total dengan GROUP BY ROLLUP

    • GROUP BY ROLLUP dapat digunakan untuk membuat subtotal dan total keseluruhan
    • Contohnya membuat baris total keseluruhan gaji sambil menghitung jumlah gaji per departemen
    • Dokumentasi Transact-SQL menjelaskan bahwa ROLLUP membuat grup untuk setiap kombinasi ekspresi kolom, mengurangi jumlah grup dari kanan ke kiri, lalu membuat subtotal dan total keseluruhan
    • Dengan menerapkan COALESCE, baris total keseluruhan dapat ditampilkan seperti Total
    • Perlu memperhatikan kolom pengurutan agar baris total keseluruhan muncul di bagian bawah hasil
  • Menemukan perbedaan dua result set dengan EXCEPT

    • EXCEPT mengembalikan baris yang ada di hasil kueri pertama tetapi tidak ada di hasil kueri kedua
    • Jika EXCEPT dan UNION ALL digunakan bersama, Anda dapat memverifikasi apakah dua tabel memiliki data yang sama
    • Jika tidak ada baris yang dikembalikan, kedua tabel identik
    • Jika ada baris yang dikembalikan, baris-baris itulah penyebab perbedaannya

Pola yang Merusak Performa dan Akurasi

  • Pada kolom yang bisa NULL, NOT EXISTS lebih baik daripada NOT IN

    • Jika kolom pembanding mengizinkan NULL, NOT IN biasanya bisa lebih lambat daripada NOT EXISTS
    • Fenomena ini dialami di Snowflake, dan Don’t Do This di PostgreSQL Wiki menyebutkan bahwa NOT IN (SELECT ...) tidak dioptimalkan dengan baik
    • NOT IN tidak bekerja sesuai harapan jika nilai pembanding memiliki NULL
    • Kolom yang mengizinkan NULL tidak berarti benar-benar ada nilai NULL, tetapi saat menangani tabel yang tidak dapat diubah, NOT EXISTS dapat membantu meningkatkan kecepatan
  • Konversi tipe implisit bisa memperlambat atau gagal

    • Jika nilai dengan tipe data berbeda dari kolom dimasukkan ke kondisi, database dapat mencoba konversi tipe implisit
    • Contohnya membahas perbandingan integer 200050 dengan kolom video_id bertipe string
    • Mengandalkan konversi tipe implisit dapat menimbulkan masalah
    • Jika ada nilai yang tidak dapat dikonversi, error dapat terjadi
    • Kueri bisa menjadi lebih lambat karena pekerjaan tambahan untuk mengonversi setiap nilai ke tipe yang ditentukan
    • Gunakan tipe data yang sama dengan kolom, atau gunakan fungsi seperti TRY_TO_NUMBER milik Snowflake untuk menghindari error
    • Dampak terhadap kecepatan bergantung pada ukuran dataset yang diproses

Kesalahan yang Sering Terjadi

  • NOT IN dan NULL

    • NOT IN tidak bekerja jika nilai pembanding memiliki NULL
    • Karena NULL merepresentasikan Unknown, engine SQL tidak dapat memverifikasi bahwa nilai yang diperiksa tidak ada dalam daftar
    • Dalam kasus ini, menggunakan NOT EXISTS adalah alternatifnya
  • Konflik alias pada field hasil kalkulasi

    • Jika nama field hasil kalkulasi dibuat sama dengan kolom yang sudah ada, perilaku yang tidak terduga dapat muncul
    • Dokumentasi GROUP BY Snowflake menyebutkan bahwa jika nama dalam klausa GROUP BY cocok dengan nama kolom dan alias sekaligus, nama kolom yang digunakan
    • Pada contoh, jika membuat alias dengan LEFT(product, 1) AS product lalu menulis GROUP BY product, pengelompokan dilakukan berdasarkan kolom product asli, bukan huruf pertama, sehingga 3 baris dikembalikan
    • Ada dua solusi
    • Gunakan alias unik seperti product_letter
    • Tulis ekspresinya secara eksplisit seperti GROUP BY LEFT(product, 1)
    • Masalah alias juga dapat terjadi pada window function
    • Dalam contoh, revenue untuk Robot diubah menjadi 0 dengan CASE, tetapi karena diterapkan setelah window function dijalankan, peringkat yang dihasilkan berbeda dari ekspektasi
    • Jika memungkinkan, gunakan alias unik atau masukkan ekspresi kalkulasi langsung ke dalam ORDER BY pada window function
  • Jelaskan kolom berasal dari tabel mana

    • Dalam kueri kompleks dengan banyak join, masalah nilai harus bisa dilacak sampai ke tabel sumber
    • Jika dua tabel berbagi nama kolom yang sama dan asal kolom tidak ditulis, RDBMS dapat mengeluarkan error
    • Contohnya memperjelas asal kolom dengan menambahkan alias tabel seperti vc.video_id dan metadata.season

Urutan Eksekusi, Dokumentasi, dan Nama Tersimpan

  • Memahami urutan eksekusi SQL

  • Baca dokumentasi sampai akhir

    • Ada kasus penggunaan GREATEST() di Snowflake untuk mengembalikan tanggal terbaru dari beberapa kolom tanggal
    • GREATEST() mengembalikan NULL jika salah satu argumennya adalah NULL
    • Jika dokumentasi dibaca lebih lanjut, GREATEST_IGNORE_NULLS() bisa digunakan alih-alih COALESCE(GREATEST(...), ...)
    • Dalam banyak kasus, memindai dokumentasi hanya membutuhkan kurang dari 1 menit dan dapat mengurangi upaya mencari penyebab perilaku yang berbeda dari ekspektasi
  • Gunakan nama deskriptif untuk kueri tersimpan

    • Untuk menghindari situasi tidak dapat menemukan kueri yang perlu dijalankan ulang atau dijadikan referensi, sebaiknya simpan dengan nama deskriptif
    • Nama tersimpan biasanya mencakup topik kueri, bulan eksekusi, dan nama peminta
    • Contohnya adalah format Lapsed users analysis - 2023-09-01 - Olivia Roberts

2 komentar

 
hiyama 2024-09-26

Koma di awal pada postingan ini semuanya ditulis sebagai koma di akhir. Di teks aslinya, koma dimasukkan di awal.

-- Good:  
SELECT   
timeslot_date  
, timeslot_channel   
, overnight_fta_share  
, IFF(DATEDIFF(DAY, timeslot_date, CURRENT_DATE()) > 7, -- First argument of IFF.  
	LAG(overnight_fta_share, 1) OVER (PARTITION BY timeslot_date, timeslot_channel ORDER BY timeslot_activity), -- Second argument of IFF.  
		NULL) AS C7_fta_share -- Third argument of IFF.  
, IFF(DATEDIFF(DAY, timeslot_date, CURRENT_DATE()) >= 29,   
		LAG(overnight_fta_share, 2) OVER (PARTITION BY timeslot_date, timeslot_channel ORDER BY timeslot_activity),   
			NULL) AS C28_fta_share  
FROM timeslot_data  
;  
 
GN⁺ 2024-09-26
Komentar Hacker News
  • Tip yang ingin saya tambahkan: pelajari server DB dengan benar dan sering-sering periksa execution plan. Hasilnya bisa mengejutkan, jadi sebaiknya sesuaikan lalu cek lagi
    Biasanya EXISTS lebih cepat daripada IN, dan NOT EXISTS berperilaku berbeda dari EXCEPT dalam penanganan NULL. Alih-alih menggabungkan tabel lalu menyaring baris dengan sesuatu seperti DISTINCT, terkadang jauh lebih cepat memakai kolom subkueri di daftar SELECT. Ini tetap bisa berlaku meski mengambil lebih dari 10 nilai dari tabel yang sama, dan meski server DB mendukung lateral join. Namun subkueri harus mengembalikan paling banyak satu baris
    Kueri yang bukan sekali pakai harus dibuat agar tidak melakukan pemindaian seluruh tabel. Pemindaian tabel hari ini bisa menjadi insiden besok, jadi tambahkan indeks. Ingat juga bahwa klausa GROUP BY biasanya menentukan penggunaan indeks
    Jika harus memfilter berdasarkan ekspresi, misalnya memeriksa apakah substring sama dengan nilai tertentu, Anda bisa menambahkan kolom terhitung dan memasang indeks di sana. Beberapa DB mendukung indeks ekspresi secara langsung. Menggunakan UNION ALL alih-alih OR sering kali bisa jauh lebih cepat, termasuk pada kueri kompleks atau banyak kondisi OR
    Saat DB tidak cukup pintar menentukan urutan pemfilteran, men-JOIN subkueri untuk memaksakan urutannya juga berguna

    • Yang paling berguna adalah mempelajari DBMS itu sendiri. Tiap DB punya kekhasan dalam performa dan tingkat isolasi, serta fitur bonus yang berbeda-beda, jadi ini tidak bisa dihindari
      Hal yang menarik di Postgres—dan mungkin juga berlaku di DB lain—adalah operasi INSERT (SELECT ...) bisa menjadi hampir lebih cepat secara linear jika di-sharding manual sesuai jumlah core CPU. Ini bisa dilakukan bahkan dengan sekitar 10 join. Pertama lihat EXPLAIN, cari join yang paling dalam atau paling luar, lalu jalankan kueri paralel terpisah untuk tiap rentang baris (id >= start AND id < end). Dalam pekerjaan 6 tahun lalu, saya banyak memakai cara ini karena alasan yang aneh. Postgres 10+ sudah menambahkan paralelisme, tetapi setahu saya belum semaju ini
    • Saya tidak tahu persis maksudnya memakai “kolom” subkueri di daftar SELECT
      Misalnya, jika menjalankan SELECT column1, (SELECT column2, column3, ... FROM table_b WHERE table_a.id = table_b.a_id) FROM table_a, hasilnya seperti yang diduga: “subquery must return only one column”. Apakah maksudnya mengembalikan beberapa kolom sebagai record/tipe komposit?
      Alasan mengapa klausa GROUP BY biasanya menentukan penggunaan indeks tidak langsung terasa jelas bagi saya, tetapi bagi yang penasaran, artikel ini menjelaskannya langkah demi langkah dengan baik: https://www.brentozar.com/archive/2015/06/indexing-for-group...
    • Setuju. Pakai EXPLAIN, dan pelajari cara menafsirkannya dengan alat pilihan Anda. Kueri juga harus dimonitor
      Di startup sebelumnya, kami memasang PgHero, dan itu sangat membantu untuk optimasi performa serta penentuan prioritas
    • Kueri yang dirancang baik pun sering berjalan tidak seperti perkiraan. Contoh umumnya adalah statistik kolom yang belum diperbarui, atau data yang terfragmentasi pada tabel besar. Misalnya seperti penyisipan primary key acak
    • Saya tidak setuju dengan “kueri yang bukan sekali pakai tidak boleh melakukan pemindaian seluruh tabel. Pemindaian tabel hari ini bisa menjadi insiden besok”
      Ada kueri yang strategi akses paling efisiennya memang pemindaian seluruh tabel. Biasanya kueri analitik/agregasi yang membaca seluruh tabel seperti itu, dan kadang bahkan saat mengambil hanya 50% dari seluruh baris, table scan tetap lebih baik.
      Saya juga kurang paham bagaimana pemindaian tabel read-only bisa berujung pada insiden. Itu karena tidak memblokir akses bersamaan. Kekurangannya hanya beban I/O yang besar, tetapi jika server tidak sanggup menangani beban sebesar itu, menurut saya sejak awal spesifikasinya memang sangat kurang
  • Tiga contoh di bagian “readability” terasa aneh. Dua yang pertama secara harfiah mengorbankan keterbacaan demi kemudahan menulis, dan yang terakhir adalah bentuk monster yang sulit dibaca dan hampir tidak tertolong bahkan dengan indentasi

    • Format koma di depan punya kelebihan selain keterbacaan. Misalnya dalam sistem version control, format satu argumen per baris + koma di depan membuat perubahan argumen hanya muncul sebagai diff satu baris
      Menurut saya developer melihat riwayat commit sama seringnya dengan kode sumber aktual
    • Saya tidak bisa bilang sangat suka bentuk dua konvensi pertama, tetapi itu memang konvensi yang benar-benar dipakai oleh orang yang menulis SQL sungguhan. Saya juga bisa memahami mengapa itu ada
      Karena sudah cukup sering melihatnya, sekarang tidak terlalu mengganggu lagi
    • Alternatifnya, tulis SQL berantakan seperti anak tiga tahun yang baru menemukan MSPaint, lalu tekan tombol “beautifier” dan pergi makan siang lebih awal
    • Saya tidak mengerti mengapa Anda menganggapnya lebih buruk
      Saya juga tidak melihat masalah
      Dan sepertinya tidak ada yang salah
    • Siapa sebenarnya yang memecah kolom di blok SELECT per baris, tetapi membiarkan baris sepanjang 150 karakter begitu saja? Ini definisi keterbacaan yang rusak. Soal koma bahkan belum sempat saya mulai
      Dalam code review, baris panjang tidak benar-benar dilihat orang. Itu masalah terbesar AngularJS. Merge salah ditangani dan semuanya rusak, karena sekitar kolom ke-90 mata mulai kabur. Saya sudah berada di lebih dari setengah lusin tim yang memakai code review, dan selalu sama. Bahkan ketika sangat sadar akan masalah ini dan berusaha menghindarinya, saya sendiri masih membuat kesalahan dengan frekuensi sekitar setengah dari orang lain
      Pecah-pecahlah barisnya. Apalagi kalau menunjukkan contoh kepada orang lain
  • Tips saat menangani stored procedure yang kompleks adalah sebagai berikut

    1. Di awal prosedur, segera salin tabel permanen ke tabel sementara, lalu tentukan/batasi/filter hanya baris yang diperlukan
    2. Di bagian tengah, manipulasi tabel sementara sesuai kebutuhan
    3. Di bagian akhir, perbarui tabel permanen di dalam transaksi. Jika terdeteksi error, segera rollback transaksi dan akhiri prosedur. Dengan mengikuti tiga langkah ini, konkurensi membaik, dan prosedur bisa dimulai ulang tanpa perlu membersihkan sisa-sisa data secara manual
    4. Saat menangani tabel jarak jauh, harus sangat berhati-hati. Karena tabel jarak jauh tidak berada di dalam RDBMS saat ini, besar kemungkinan statistik atau indeks RDBMS tersebut hampir tidak bisa dimanfaatkan. Dalam banyak kasus, lebih cepat untuk men-dump/menyalin seluruh tabel jarak jauh ke tabel sementara lalu mengerjakannya. Hal maksimal yang bisa diharapkan dari tabel jarak jauh hanyalah eksekusi klausa WHERE. Jika mencoba JOIN atau operasi kompleks, kemungkinan besar akan timeout
    5. Execution plan mudah membingungkan. Dalam beberapa kasus, execution plan bisa jatuh ke pemrosesan per baris sehingga performa berhenti total. Sering kali lebih baik memecah stored procedure yang kompleks menjadi langkah-langkah kecil yang memakai tabel sementara
    6. Untuk melihat apa yang sebenarnya dilakukan RDBMS, selalu periksa execution plan
    • Saya pernah secara signifikan meningkatkan performa query dengan membatalkan kode yang menerapkan poin 5 pada situasi yang sebenarnya tidak membutuhkannya. Terkadang memecah query menjadi beberapa query kecil jauh lebih tidak efisien dibanding memberi query optimizer seluruh query dan membiarkannya menemukan jalur optimal
      Jika melakukan poin 5 tanpa poin 6, besar kemungkinan Anda tidak akan melihat bahwa Anda sedang melakukan sesuatu yang tidak optimal. Saran saya adalah hindari optimasi dini: tulis dulu dengan cara yang paling intuitif, lalu optimalkan hanya saat diperlukan. Yang terpenting adalah jangan menulis SQL secara prosedural. Anda mendeskripsikan data yang diinginkan, bukan memerintahkan engine bagaimana cara mengambilnya
    • Saya tidak suka harus memakai banyak tabel sementara, tetapi saya sering menjumpai query yang tidak akan pernah selesai jika diserahkan ke query planner. Seperti compiler, kemampuan query planner juga sangat dilebih-lebihkan
      Di sisi lain, Microsoft terus memasang peringatan agar kita tidak mencoba melakukan tuning terhadapnya, seolah-olah query planner-lah yang paling tahu
    • Aturan-aturan ini bisa sepenuhnya benar pada DB dari vendor tertentu, tetapi DB lain bisa memiliki prioritas, karakteristik, dan trade-off yang sangat berbeda
      Versi DB juga bisa berpengaruh
    • Poin 1–3 tidak masalah jika Anda bisa menjamin ukuran datanya masuk akal. Namun jika data menjadi terlalu besar untuk ditangani hardware, menyalin dataset besar lalu memperbarui kembali dataset besar dapat menambahkan overhead yang cukup besar
  • Saya tidak suka pengembangan “untuk berjaga-jaga”. Begitu juga dengan interface, maupun placeholder seperti where 1=1
    Lakukan saat diperlukan. Jangan melakukannya hanya karena mungkin suatu hari di masa depan akan dibutuhkan. Kode produksi bukan tempat untuk meninggalkan helper pengembangan. Saat pengembangan, silakan lakukan sesuka hati, tetapi dalam kode produksi, keterbacaan dan maksud yang jelas jauh lebih penting

    • Apakah Anda cenderung menulis semua referensi nama tabel dan nama kolom dengan kualifikasi lengkap? Sering kali itu membuat keterbacaan meningkat lebih dari satu digit, tetapi dengan cepat menjadi sangat bertele-tele dan luar biasa membosankan untuk ditulis
  • Satu tambahan tentang “anti join”. Jika hanya ingin memeriksa apakah baris yang memenuhi kondisi ada di tabel besar lain atau subquery, sebaiknya gunakan EXISTS alih-alih IN atau LEFT JOIN
    EXISTS mengembalikan true segera setelah menemukan item yang cocok. Pada LEFT JOIN dan IN, engine mengumpulkan semua hasil sebelum evaluasi

    • Bagian itu agak membingungkan bagi saya. Dalam semua kasus yang saya uji, (NOT) EXISTS menghasilkan execution plan yang lebih baik daripada (LEFT) JOIN atau (NOT) IN, atau menghasilkan plan yang sama
      Selain itu, niatnya juga lebih jelas
  • Terkait “beri komentar pada kode”, setidaknya di MSSQL sering disarankan memakai /**/ alih-alih -- untuk komentar. Ini karena fitur seperti Query Store sering menyimpan query tanpa baris baru, sehingga ketika query diambil dari sana, kita harus memperbaiki semuanya secara manual alih-alih langsung memakai formatter IDE

    • Itu terdengar seperti bug di Query Store
    • Bisa di-cast ke XML? Saya memakai itu pada OBJECT_DEFINITION
      select name,cast((select OBJECT_DEFINITION(object_id) for xml path('')) as xml) from sys.procedures
      Karena baris baru dipertahankan, mungkin lebih mudah untuk merapikannya. Namun karakter XML lain akan rusak, seperti > berubah menjadi >. Pilihan lain adalah memakai VARBINARY dan sesuatu untuk mengurainya kembali
  • Semua orang ribut soal saran koma, tetapi apakah 1=1 di klausa WHERE dianggap ide bagus? Kalau melihat itu dalam code review, saya tidak tahu harus berpikir apa tentang penulisnya

    • Itu bisa dibenarkan dengan alasan yang sama seperti trailing comma. Alasannya adalah perubahan pada pernyataan WHERE tidak memengaruhi baris lain sehingga code review menjadi lebih mudah
      Namun jika alasannya untuk menambahkan kondisi dinamis seperti dalam kasus ini, di tempat saya bekerja orang itu pasti akan dipecat
  • Apakah ada yang bisa berbagi panduan umum tentang di mana sebaiknya menarik garis antara meningkatkan kecepatan lewat konfigurasi DB—cara yang hampir seperti “membeli”—dan “membangun” yang pada dasarnya diimplementasikan secara manual? Dari pengalaman saya yang terbatas, DBA yang kompeten mendapat bayaran jauh lebih tinggi dan bekerja di tempat lain, sehingga pekerjaan ini sering jatuh ke developer aplikasi. Seperti disebutkan di atas, memahami DB itu penting
    Contoh yang representatif adalah data yang menumpuk dalam jumlah besar seiring waktu, dan data terbaru paling sering diakses. DBA bisa menjaga akses tetap cepat dengan partitioning atau partial index, tetapi developer aplikasi juga bisa memindahkan record ke tabel arsip terpisah di belakang layar sambil tetap mendukung fitur seperti pencarian akhir atas seluruh dataset. Saya juga merasa pekerjaan awal untuk memecah satu tabel menjadi beberapa tabel pada waktu yang tepat bisa cukup diautomasi oleh tool, misalnya ketika terbatas oleh kurangnya fitur pada cloud DB
    Pilihan pengelolaan lain adalah menyimpan semua blob/file besar di database terpisah, atau di file system, untuk memakai konfigurasi storage yang berbeda. Ini juga bisa ditangani oleh DB maupun secara manual
    Dalam kasus ekstrem, sepertinya bisa sampai mengimplementasikan index sendiri. Caranya dengan memiliki tabel raksasa berisi satu primary key auto-increment dan banyak sekali kolom, lalu membuat tabel terpisah yang berisi ID tersebut dan beberapa kolom yang dapat dicari. Bahkan bisa saja sampai ke full-text search atau vector
    Tips yang berguna saat mengimplementasikan pola materialized view secara manual di MSSQL 2016+ adalah menggunakannya bersama partition switching. Ini dijelaskan dan diimplementasikan dengan baik di https://github.com/cajuncoding/SqlBulkHelpers?tab=readme-ov-.... Itu adalah library kecil yang saya temukan secara kebetulan; paling berguna secara komersial, tetapi peringkat pencariannya rendah dan bintangnya sedikit, serta berfokus pada bulk insert ke MSSQL dengan .NET. Saya pikir ini contoh yang bagus tentang menarik garis beli/bangun dengan tepat melalui otomatisasi partition switching

  • Yang terlewat: harus berhenti memakai SELECT *. Hampir pasti Anda tidak membutuhkan seluruh lebar tabel, dan dengan begitu Anda menambah data yang harus difilter dan dikirim, sekaligus menghalangi fitur keren bernama semi join

    • Orang yang memakai SQL secara garis besar ada dua kelompok: analis dan developer
      Kalau Anda developer, benar. SELECT * punya jebakan, dan hampir selalu sebaiknya menyebutkan kolom secara eksplisit, atau memakai query builder yang melakukannya untuk Anda
      Tapi kalau Anda analis, hidup ini singkat, dan kadang Anda tidak ingin mengetik semua kolom satu per satu. SELECT * juga tidak apa-apa
  • Mungkin agak keluar dari topik, tetapi apakah bisa diterima jika maintainer langsung menutup pull request tanpa komentar atau diskusi apa pun?
    Saya bertanya sebagai orang yang sesekali pernah berkontribusi, atau mencoba berkontribusi, ke repository
    Contoh: https://github.com/ben-n93/SQL-tips-and-tricks/pulls?q=is%3A...