Saya pernah mendengar bahwa SELECT *
ini adalah praktik yang buruk untuk digunakan ketika menulis perintah SQL karena lebih efisien untuk SELECT
kolom yang Anda butuhkan secara khusus.
Jika saya perlu SELECT
setiap kolom dalam sebuah tabel, harus saya gunakan
SELECT * FROM TABLE
atau
SELECT column1, colum2, column3, etc. FROM TABLE
Apakah efisiensi benar-benar penting dalam kasus ini? Saya pikir SELECT *
akan lebih optimal secara internal jika Anda benar-benar membutuhkan semua data, tetapi saya mengatakan ini tanpa pemahaman nyata tentang database.
Saya ingin tahu apa praktik terbaik dalam kasus ini.
UPDATE: Saya mungkin harus menentukan bahwa satu-satunya situasi di mana saya benar-benar ingin melakukanSELECT *
adalah ketika saya memilih data dari satu tabel di mana saya tahu semua kolom akan selalu perlu diambil, bahkan ketika kolom baru ditambahkan.
Namun, dengan tanggapan yang saya lihat, ini sepertinya ide yang buruk dan SELECT *
tidak boleh digunakan untuk alasan teknis yang lebih banyak yang pernah saya pikirkan.
Jawaban:
Salah satu alasan memilih kolom tertentu lebih baik adalah karena meningkatkan kemungkinan SQL Server dapat mengakses data dari indeks daripada meminta kueri data tabel.
Inilah postingan yang saya tulis tentang hal itu: Alasan sebenarnya memilih kueri adalah cakupan indeks yang buruk
Juga kurang rapuh untuk berubah, karena kode apa pun yang menggunakan data akan mendapatkan struktur data yang sama terlepas dari perubahan yang Anda buat pada skema tabel di masa mendatang.
sumber
vs
all_column_names) sementara kami memiliki ribuan baris dan kami melakukan SELECT dengan indeks (dalam klausa WHERE) ??Mengingat Anda spesifikasi yang Anda sedang memilih semua kolom, ada sedikit perbedaan pada saat ini . Namun, sadari bahwa skema database memang berubah. Jika Anda menggunakan,
SELECT *
Anda akan mendapatkan kolom baru ditambahkan ke tabel, meskipun kemungkinan besar, kode Anda tidak siap untuk menggunakan atau menyajikan data baru itu. Ini berarti bahwa Anda mengekspos sistem Anda terhadap perubahan kinerja dan fungsi yang tidak terduga.Anda mungkin bersedia mengabaikan ini sebagai biaya kecil, tetapi sadarilah bahwa kolom yang tidak Anda perlukan tetap harus:
Item # 1 memiliki banyak biaya tersembunyi termasuk menghilangkan beberapa indeks penutup potensial, menyebabkan pemuatan halaman data (dan cache server merosot), menimbulkan kunci baris / halaman / tabel yang mungkin bisa dihindari.
Seimbangkan ini dengan penghematan potensial dengan menentukan kolom versus kolom dan satu
*
-satunya potensi penghematan adalah:Untuk item 1, kenyataannya adalah Anda akan menambahkan / mengubah kode untuk menggunakan kolom baru apa pun yang mungkin Anda tambahkan, jadi ini adalah cuci.
Untuk item 2, perbedaannya jarang cukup untuk mendorong Anda ke ukuran paket atau jumlah paket jaringan yang berbeda. Jika Anda sampai pada titik di mana waktu transmisi pernyataan SQL adalah masalah utama, Anda mungkin perlu mengurangi tingkat pernyataan terlebih dahulu.
Untuk item 3, tidak ada penghematan karena perluasan
*
harus tetap terjadi, yang berarti tetap berkonsultasi dengan skema tabel. Secara realistis, daftar kolom akan dikenakan biaya yang sama karena harus divalidasi terhadap skema. Dengan kata lain ini adalah mencuci lengkap.Untuk item 4, ketika Anda menentukan kolom tertentu, cache rencana kueri Anda bisa menjadi lebih besar tetapi hanya jika Anda berurusan dengan set kolom yang berbeda (yang bukan yang Anda tentukan). Dalam hal ini, Anda ingin entri cache yang berbeda karena Anda ingin paket yang berbeda sesuai kebutuhan.
Jadi, ini semua turun, karena cara Anda menentukan pertanyaan, untuk masalah ketahanan dalam menghadapi modifikasi skema akhirnya. Jika Anda membakar skema ini ke dalam ROM (itu terjadi), maka sebuah
*
sangat diterima.Namun, pedoman umum saya adalah bahwa Anda hanya harus memilih kolom yang Anda butuhkan, yang berarti bahwa kadang - kadang akan terlihat seperti Anda meminta semuanya, tetapi DBA dan evolusi skema berarti bahwa beberapa kolom baru mungkin muncul yang dapat sangat mempengaruhi permintaan. .
Saran saya adalah Anda harus SELALU MEMILIH kolom tertentu . Ingatlah bahwa Anda menjadi baik pada apa yang Anda lakukan berulang-ulang, jadi biasakan melakukannya dengan benar.
Jika Anda bertanya-tanya mengapa suatu skema dapat berubah tanpa mengubah kode, pikirkan dalam hal pencatatan audit, tanggal efektif / kedaluwarsa dan hal-hal serupa lainnya yang ditambahkan oleh DBA untuk masalah kepatuhan secara sistemik. Sumber lain dari perubahan curang adalah denormalisasi untuk kinerja di tempat lain dalam sistem atau bidang yang ditentukan pengguna.
sumber
Anda hanya harus memilih kolom yang Anda butuhkan. Bahkan jika Anda membutuhkan semua kolom, masih lebih baik untuk membuat daftar nama kolom sehingga server sql tidak perlu membuat tabel sistem untuk kolom.
Selain itu, aplikasi Anda mungkin rusak jika seseorang menambahkan kolom ke tabel. Program Anda akan mendapatkan kolom yang tidak diharapkan juga dan mungkin tidak tahu cara memprosesnya.
Terlepas dari ini jika tabel memiliki kolom biner maka permintaan akan jauh lebih lambat dan menggunakan lebih banyak sumber daya jaringan.
sumber
Ada empat alasan utama yang
select *
merupakan hal buruk:Alasan praktis yang paling signifikan adalah bahwa hal itu memaksa pengguna untuk secara ajaib mengetahui urutan kolom yang akan dikembalikan. Lebih baik untuk menjadi eksplisit, yang juga melindungi Anda terhadap perubahan tabel, yang membagi menjadi ...
Jika nama kolom yang Anda gunakan berubah, lebih baik untuk menangkapnya lebih awal (pada titik panggilan SQL) daripada saat Anda mencoba menggunakan kolom yang sudah tidak ada lagi (atau sudah diubah namanya, dll. )
Mendaftar nama kolom membuat kode Anda jauh lebih terdokumentasi sendiri, dan mungkin lebih mudah dibaca.
Jika Anda mentransfer melalui jaringan (atau bahkan jika tidak), kolom yang tidak Anda butuhkan hanyalah pemborosan.
sumber
*
menjadi serangkaian nama.)Menentukan daftar kolom biasanya merupakan pilihan terbaik karena aplikasi Anda tidak akan terpengaruh jika seseorang menambahkan / memasukkan kolom ke tabel.
sumber
Menentukan nama kolom jelas lebih cepat - untuk server. Tapi jika
maka Anda lebih baik bertahan dengan SELECT *. Dalam kerangka kerja kami, penggunaan SELECT * yang berat memungkinkan kami untuk memperkenalkan bidang konten yang dikelola situs web baru ke sebuah tabel, memberikan semua manfaat CMS (versi, alur kerja / persetujuan, dll.), Sementara hanya menyentuh kode pada suatu beberapa poin, bukannya beberapa lusin poin.
Saya tahu guru DB akan membenci saya untuk ini - silakan, pilih saya turun - tetapi di dunia saya, waktu pengembang langka dan siklus CPU berlimpah, jadi saya menyesuaikan sesuai apa yang saya simpan dan apa yang saya buang.
sumber
SELECT * adalah praktik yang buruk bahkan jika kueri tidak dikirim melalui jaringan.
Tentu saja, semua ini tidak terlalu menjadi masalah bagi sistem yang kecil dan sederhana.
sumber
Dari segi kinerja, SELECT dengan kolom tertentu dapat lebih cepat (tidak perlu membaca semua data). Jika kueri Anda benar-benar menggunakan SEMUA kolom, PILIH dengan parameter eksplisit masih lebih disukai. Perbedaan kecepatan pada dasarnya tidak akan terlihat dan mendekati waktu konstan. Suatu hari skema Anda akan berubah, dan ini adalah asuransi yang baik untuk mencegah masalah karena ini.
sumber
Banyak alasan bagus dijawab di sini sejauh ini, ini satu lagi yang belum disebutkan.
Penamaan kolom secara eksplisit akan membantu Anda dengan pemeliharaan di jalan. Pada titik tertentu Anda akan membuat perubahan atau pemecahan masalah, dan menemukan diri Anda bertanya "di mana sih kolom yang digunakan".
Jika Anda memiliki nama-nama yang tercantum secara eksplisit, maka menemukan setiap referensi ke kolom itu - melalui semua prosedur tersimpan Anda, tampilan, dll - mudah. Cukup buang skrip CREATE untuk skema DB Anda, dan cari teksnya.
sumber
pasti mendefinisikan kolom, karena SQL Server tidak perlu melakukan pencarian pada kolom untuk menariknya. Jika Anda menentukan kolom, maka SQL dapat melewati langkah itu.
sumber
Itu selalu lebih baik untuk menentukan kolom yang Anda butuhkan, jika Anda memikirkannya satu kali, SQL tidak harus berpikir "wtf is *" setiap kali Anda query. Selain itu, seseorang nanti dapat menambahkan kolom ke tabel yang sebenarnya tidak Anda butuhkan dalam kueri Anda dan Anda akan lebih baik dalam hal itu dengan menentukan semua kolom Anda.
sumber
Masalah dengan "select *" adalah kemungkinan membawa data yang sebenarnya tidak Anda butuhkan. Selama permintaan basis data aktual, kolom yang dipilih tidak benar-benar menambah perhitungan. Apa yang benar-benar "berat" adalah transportasi data kembali ke klien Anda, dan kolom apa pun yang tidak benar-benar Anda butuhkan hanyalah membuang bandwidth jaringan dan menambah waktu yang Anda tunggu untuk dikembalikan.
Bahkan jika Anda menggunakan semua kolom yang dibawa dari "select * ...", itu hanya untuk saat ini. Jika di masa depan Anda mengubah tata letak tabel / tampilan dan menambahkan lebih banyak kolom, Anda akan mulai membawanya di pilihan Anda bahkan jika Anda tidak membutuhkannya.
Poin lain di mana pernyataan "pilih *" buruk adalah pada pembuatan tampilan. Jika Anda membuat tampilan menggunakan "pilih *" dan kemudian menambahkan kolom ke tabel Anda, definisi tampilan dan data yang dikembalikan tidak cocok, dan Anda harus mengkompilasi ulang tampilan Anda agar bisa berfungsi lagi.
Saya tahu bahwa menulis "pilih *" menggoda, karena saya benar-benar tidak suka menentukan secara manual semua bidang pada permintaan saya, tetapi ketika sistem Anda mulai berevolusi, Anda akan melihat bahwa ada baiknya menghabiskan waktu ekstra ini / usaha dalam menentukan bidang daripada menghabiskan lebih banyak waktu dan upaya menghilangkan bug pada tampilan Anda atau mengoptimalkan aplikasi Anda.
sumber
Meskipun secara eksplisit daftar kolom bagus untuk kinerja, jangan menjadi gila.
Jadi, jika Anda menggunakan semua data, coba SELECT * untuk kesederhanaan (bayangkan memiliki banyak kolom dan melakukan GABUNG ... kueri mungkin menjadi mengerikan). Lalu - ukur. Bandingkan dengan kueri dengan nama kolom yang tercantum secara eksplisit.
Jangan berspekulasi tentang kinerja, ukurlah!
Cantuman eksplisit sangat membantu ketika Anda memiliki beberapa kolom yang berisi data besar (seperti badan tulisan atau artikel), dan tidak memerlukannya dalam kueri yang diberikan. Maka dengan tidak mengembalikannya di server DB jawaban Anda dapat menghemat waktu, bandwidth, dan throughput disk. Hasil kueri Anda juga akan lebih kecil, yang bagus untuk setiap cache kueri.
sumber
Anda harus benar-benar memilih hanya bidang yang Anda butuhkan, dan hanya nomor yang diperlukan, yaitu
Di luar basis data, kueri dinamis menjalankan risiko serangan injeksi dan data cacat. Biasanya Anda menyelesaikan ini menggunakan prosedur tersimpan atau kueri parameterised. Juga (walaupun tidak terlalu banyak masalah) server harus membuat rencana eksekusi setiap kali query dinamis dieksekusi.
sumber
Pilih sama efisiennya (dalam hal kecepatan) jika Anda menggunakan * atau kolom.
Perbedaannya adalah tentang memori, bukan kecepatan. Ketika Anda memilih beberapa kolom SQL Server harus mengalokasikan ruang memori untuk melayani Anda permintaan, termasuk semua data untuk semua kolom yang Anda minta, bahkan jika Anda hanya menggunakan salah satunya.
Yang penting dalam hal kinerja adalah rencana eksekusi yang pada gilirannya sangat bergantung pada klausa WHERE Anda dan jumlah JOIN, OUTER JOIN, dll ...
Untuk pertanyaan Anda cukup gunakan SELECT *. Jika Anda membutuhkan semua kolom tidak ada perbedaan kinerja.
sumber
BUKAN lebih cepat menggunakan nama bidang eksplisit versus *, jika dan hanya jika, Anda perlu mendapatkan data untuk semua bidang.
Perangkat lunak klien Anda seharusnya tidak bergantung pada urutan bidang yang dikembalikan, jadi itu juga omong kosong.
Dan mungkin (walaupun tidak mungkin) Anda perlu mendapatkan semua bidang menggunakan * karena Anda belum tahu bidang apa yang ada (pikirkan struktur basis data yang sangat dinamis).
Kerugian lain menggunakan nama bidang eksplisit adalah bahwa jika ada banyak dari mereka dan mereka panjang maka itu membuat membaca kode dan / atau log kueri lebih sulit.
Jadi aturannya adalah: jika Anda membutuhkan semua bidang, gunakan *, jika Anda hanya perlu satu bagian, beri nama secara eksplisit.
sumber
Hasilnya terlalu besar. Ini lambat untuk menghasilkan dan mengirim hasil dari mesin SQL ke klien.
Sisi klien, sebagai lingkungan pemrograman generik, tidak dan tidak boleh dirancang untuk memfilter dan memproses hasilnya (misalnya klausa WHERE, klausa ORDER), karena jumlah baris bisa sangat besar (mis. Puluhan juta baris).
sumber
Memberi nama setiap kolom yang Anda harapkan dalam aplikasi Anda juga memastikan aplikasi Anda tidak akan rusak jika seseorang mengubah tabel, selama kolom Anda masih ada (dalam urutan apa pun).
sumber
Itu tergantung pada versi server DB Anda, tetapi versi SQL modern dapat men-cache rencana itu. Saya akan mengatakan pergi dengan apa pun yang paling dipelihara dengan kode akses data Anda.
sumber
Salah satu alasan mengapa lebih baik mengeja kolom mana yang Anda inginkan adalah karena kemungkinan perubahan di masa depan dalam struktur tabel.
Jika Anda membaca data secara manual menggunakan pendekatan berbasis indeks untuk mengisi struktur data dengan hasil kueri Anda, maka di masa mendatang ketika Anda menambah / menghapus kolom Anda akan sakit kepala mencoba untuk mencari tahu apa yang salah.
Mengenai apa yang lebih cepat, saya akan tunduk kepada orang lain karena keahlian mereka.
sumber
Seperti kebanyakan masalah, itu tergantung pada apa yang ingin Anda capai. Jika Anda ingin membuat kisi db yang memungkinkan semua kolom dalam tabel apa pun, maka "Pilih *" adalah jawabannya. Namun, jika Anda hanya perlu kolom tertentu dan menambah atau menghapus kolom dari kueri dilakukan jarang, maka tentukan secara individual.
Itu juga tergantung pada jumlah data yang ingin Anda transfer dari server. Jika salah satu kolom didefinisikan sebagai memo, grafik, gumpalan, dll. Dan Anda tidak memerlukan kolom itu, sebaiknya Anda tidak menggunakan "Pilih *" atau Anda akan mendapatkan sejumlah besar data yang tidak Anda perlukan. inginkan dan kinerja Anda dapat menderita.
sumber
Untuk menambahkan apa yang dikatakan orang lain, jika semua kolom yang Anda pilih dimasukkan dalam indeks, set hasil Anda akan ditarik dari indeks alih-alih mencari data tambahan dari SQL.
sumber
SELECT * diperlukan jika seseorang ingin mendapatkan metadata seperti jumlah kolom.
sumber
Apa yang dikatakan semua orang di atas, ditambah:
Jika Anda berupaya mendapatkan kode yang dapat dibaca yang dapat dibaca, lakukan sesuatu seperti:
PILIH foo, bilah DARI widget;
langsung dibaca dan menunjukkan niat. Jika Anda melakukan panggilan itu, Anda tahu apa yang Anda dapatkan kembali. Jika widget hanya memiliki kolom foo dan bilah, maka memilih * berarti Anda masih harus memikirkan apa yang Anda dapatkan kembali, mengonfirmasi pesanan dipetakan dengan benar, dll. Namun, jika widget memiliki lebih banyak kolom tetapi Anda hanya tertarik pada foo dan bar, maka kode Anda menjadi berantakan ketika Anda meminta wildcard dan kemudian hanya menggunakan sebagian dari apa yang dikembalikan.
sumber
Dan ingat jika Anda memiliki gabungan internal dengan definisi Anda tidak perlu semua kolom karena data di kolom gabungan diulang.
Ini tidak seperti daftar kolom di server SQl sulit atau bahkan memakan waktu. Anda cukup menyeret mereka dari browser objek (Anda bisa mendapatkan semuanya sekaligus dengan menyeret dari kolom kata). Untuk membuat hit kinerja permanen pada sistem Anda (karena ini dapat mengurangi penggunaan indeks dan karena mengirim data yang tidak dibutuhkan melalui jaringan mahal) dan membuatnya lebih mungkin bahwa Anda akan memiliki masalah yang tidak terduga karena perubahan database (kadang-kadang kolom ditambahkan bahwa Anda tidak ingin pengguna melihat misalnya) hanya untuk menghemat kurang dari satu menit waktu pengembangan adalah pandangan pendek dan tidak profesional.
sumber
Dari segi kinerja, saya telah melihat komentar bahwa keduanya sama. tetapi aspek kegunaan ada beberapa + dan -'s
Saat Anda menggunakan (pilih *) dalam kueri dan jika seseorang mengubah tabel dan menambahkan bidang baru yang tidak perlu untuk kueri sebelumnya, itu adalah overhead yang tidak perlu. Dan bagaimana jika bidang yang baru ditambahkan adalah gumpalan atau bidang gambar ??? waktu respons kueri Anda akan sangat lambat.
Di sisi lain, jika Anda menggunakan (pilih col1, col2, ..) dan jika tabel diubah dan menambahkan bidang baru dan jika bidang-bidang tersebut diperlukan di set hasil, Anda selalu perlu mengedit kueri pemilihan Anda setelah perubahan tabel.
Tapi saya sarankan untuk selalu menggunakan pilih col1, col2, ... di kueri Anda dan ubah kueri jika tabel diubah nanti ...
sumber
Tentukan kolom yang ingin Anda SELECT setiap saat. Tidak ada alasan untuk tidak melakukannya dan peningkatan kinerja tidak sia-sia.
Mereka seharusnya tidak pernah memberikan opsi untuk "SELECT *"
sumber
Jika Anda memerlukan setiap kolom maka cukup gunakan SELECT * tetapi ingat bahwa pesanan berpotensi berubah jadi ketika Anda mengkonsumsi hasilnya akses mereka dengan nama dan bukan dengan indeks.
Saya akan mengabaikan komentar tentang bagaimana * perlu pergi mendapatkan daftar - kemungkinan parsing dan memvalidasi kolom bernama sama dengan waktu pemrosesan jika tidak lebih. Jangan mengoptimalkan secara prematur ;-)
sumber
Dalam hal efisiensi pelaksanaan, saya tidak mengetahui adanya perbedaan yang signifikan. Tetapi untuk efisiensi programmer saya akan menulis nama bidang karena
sumber
hei, bersikap praktis. gunakan pilih * saat membuat prototipe dan pilih kolom tertentu saat menerapkan dan menggunakan. dari perspektif rencana eksekusi, keduanya relatif identik pada sistem modern. Namun, memilih kolom tertentu membatasi jumlah data yang harus diambil dari disk, disimpan dalam memori dan dikirim melalui jaringan.
akhirnya rencana terbaik adalah memilih kolom tertentu.
sumber