Saya bertanya karena begitu banyak pertanyaan yang saya lihat dalam jumlah SQL untuk: "Ini lambat. Bagaimana saya mempercepatnya"? Atau apakah tutorial menyatakan "Lakukan ini dengan cara ini dan jangan seperti itu karena lebih cepat".
Tampak bagi saya bahwa sebagian besar dari SQL mengetahui bagaimana ekspresi akan dilakukan dan dari pengetahuan itu memilih gaya ekspresi yang berkinerja lebih baik. Ini tidak sesuai dengan satu aspek pemrograman deklaritif - yaitu meninggalkan sistem untuk memutuskan cara terbaik untuk melakukan perhitungan dengan Anda hanya menentukan apa yang harus dihasilkan perhitungan.
Bukankah seharusnya mesin SQL tidak peduli jika Anda menggunakan in
, exists
atau join
jika itu benar-benar deklaratif tidak hanya memberi Anda jawaban yang benar dalam waktu yang wajar jika memungkinkan dengan salah satu dari tiga metode ini? Contoh terakhir ini diminta oleh posting terbaru ini yang merupakan jenis yang disebutkan dalam paragraf pembuka saya.
Indeks
Saya kira contoh termudah yang bisa saya gunakan terkait dengan membuat indeks untuk tabel. Gumph di sini di w3schools.com bahkan mencoba menjelaskannya sebagai sesuatu yang tidak terlihat oleh pengguna yang ada karena alasan kinerja. Deskripsi mereka tampaknya menempatkan indeks SQL di kamp non-deklaratif dan mereka secara rutin ditambahkan dengan tangan karena alasan murni kinerja.
Apakah ini kasus mereka di suatu tempat yang ideal SQL DB yang jauh lebih deklaratif daripada yang lain tetapi karena itu yang baik tidak mendengar tentang hal itu?
sumber
select whatever from sometable where FKValue in (select FKValue from sometable_2 where other_value = :param)
. Itu harus sepele untuk melihat bagaimana menyatakan kembali itu denganexists
ataujoin
.Jawaban:
SQL secara teoritis bersifat deklaratif. Tapi Anda tahu apa yang mereka katakan tentang perbedaan antara teori dan praktek ...
Pada intinya, konsep "pemrograman deklaratif" tidak pernah benar-benar efektif, dan kemungkinan tidak akan pernah sampai kita memiliki kompiler berbasis AI yang mampu melihat kode dan menjawab pertanyaan "apa tujuan dari kode ini?" secara cerdas, dengan cara yang sama seperti orang yang menulisnya. Inti dari setiap bahasa deklaratif adalah sejumlah besar kode imperatif yang berusaha dengan panik memecahkan masalah itu tanpa bantuan AI.
Seringkali ini bekerja dengan sangat baik, karena kasus yang paling umum adalah kasus yang umum , yang diketahui orang-orang yang menulis implementasi bahasa dan menemukan cara yang baik untuk mengatasinya. Tetapi kemudian Anda menghadapi kasus tepi yang tidak dipertimbangkan oleh implementor, dan Anda melihat kinerja menurun dengan cepat karena penerjemah dipaksa untuk mengambil kode secara lebih harfiah dan menanganinya dengan cara yang kurang efisien.
sumber
I rarely hit an edge case in any of them that couldn't be solved within the framework.
Ya, itulah intinya: harus mencari cara untuk menyelesaikannya dalam kerangka karena kerangka tidak cukup pintar untuk menyelesaikannya untuk Anda seperti cara Anda menyatakannya.Saya memikirkan ini beberapa hari yang lalu setelah optimasi SQL. Saya pikir kita bisa sepakat bahwa SQL adalah "bahasa deklaratif" dalam definisi Wikipedia:
Jika Anda berpikir berapa banyak hal yang dilakukan di balik tirai (melihat statistik, memutuskan apakah indeks berguna, mencari bergabung, bergabung atau hash bergabung, dll. Dll.) Kita harus mengakui bahwa kita hanya memberikan tingkat tinggi logika, dan database menangani semua logika aliran kontrol level rendah.
Juga dalam skenario ini, kadang-kadang pengoptimal database membutuhkan beberapa "petunjuk" dari pengguna untuk memberikan hasil terbaik.
Definisi umum lain dari bahasa "deklaratif" adalah (saya tidak dapat menemukan sumber otoritatif):
Jika kami menerima definisi ini, kami menghadapi masalah yang dijelaskan oleh OP.
Masalah pertama adalah bahwa SQL memberi kita beberapa cara yang setara untuk mendefinisikan "hasil yang sama". Mungkin itu adalah kejahatan yang diperlukan: semakin banyak kekuatan ekspresif yang kita berikan pada suatu bahasa, semakin besar kemungkinannya memiliki cara berbeda untuk mengekspresikan hal yang sama.
Sebagai contoh, saya pernah diminta untuk mengoptimalkan kueri ini:
Karena jenisnya jauh lebih sedikit daripada pelanggan dan ada indeks di
cust_type
atas meja pelanggan, saya telah mencapai peningkatan besar dengan menulis ulang sebagai:Dalam kasus khusus ini, ketika saya bertanya kepada pengembang apa yang ingin dia capai, dia mengatakan kepada saya, "Saya ingin semua jenis pelanggan yang saya miliki setidaknya satu pelanggan", yang kebetulan persis seperti yang dijelaskan oleh kueri pengoptimal.
Jadi, jika saya dapat menemukan kueri yang setara dan lebih efisien, mengapa pengoptimal tidak dapat melakukan hal yang sama?
Tebakan terbaik saya adalah karena dua alasan utama:
SQL mengungkapkan logika:
karena SQL mengekspresikan logika tingkat tinggi, apakah kita benar-benar ingin pengoptimal untuk "mengakali" kita dan logika kita? Saya akan dengan antusias meneriakkan "ya" jika bukan karena berkali-kali saya harus memaksa pengoptimal memilih jalur eksekusi paling efisien. Saya pikir idenya mungkin untuk memungkinkan pengoptimal untuk melakukan yang terbaik (juga merevisi logika kami) tetapi memberi kami "mekanisme petunjuk" untuk datang ke penyelamatan ketika sesuatu menjadi gila (itu akan seperti memiliki roda + rem di sebuah mobil otonom).
Lebih banyak pilihan = lebih banyak waktu
Bahkan pengoptimal RDBMS terbaik tidak menguji SEMUA jalur eksekusi yang mungkin, karena mereka harus sangat cepat: seberapa bagus untuk mengoptimalkan kueri dari 100 ms hingga 10 ms jika saya perlu menghabiskan setiap waktu 100 ms untuk memilih jalur terbaik? Dan itu dengan optimizer yang menghormati "logika tingkat tinggi" kami. Jika juga harus menguji semua kueri SQL yang setara, waktu pengoptimal dapat tumbuh beberapa kali.
Contoh bagus lain dari permintaan menulis ulang yang tidak dapat dilakukan RDBMS adalah (dari posting blog yang menarik ini )
daripada yang dapat ditulis sebagai ini (Fungsi analitis diperlukan)
sumber