Saat ini saya sedang membuat aplikasi web yang memungkinkan pengguna untuk menyimpan dan berbagi file, berukuran 1 MB - 10 MB.
Sepertinya saya bahwa menyimpan file dalam database akan secara signifikan memperlambat akses database.
Apakah ini masalah yang valid? Apakah lebih baik menyimpan file dalam sistem file dan menyimpan nama file dan path dalam database? Adakah praktik terbaik yang terkait dengan menyimpan file saat bekerja dengan database?
Saya bekerja di PHP dan MySQL untuk proyek ini, tetapi masalah ini sama untuk sebagian besar lingkungan ( Ruby on Rails , PHP , .NET ) dan basis data (MySQL, PostgreSQL ).
database
database-design
mysql
file-handling
B Tujuh
sumber
sumber
10MB
sebesar dalam sistem modern.Jawaban:
Alasan yang mendukung menyimpan file dalam database:
Alasan penyimpanan file dalam database:
FILESTREAM
dan perlu bermigrasi ke sistem database yang berbeda.IMO, menganggap penyimpanan file dalam database atau tidak sebagai "buruk" memerlukan informasi lebih lanjut tentang keadaan dan persyaratan. Apakah ukuran dan / atau jumlah file selalu kecil? Apakah tidak ada rencana untuk menggunakan penyimpanan cloud? Apakah file akan disajikan di situs web atau biner yang dapat dijalankan seperti aplikasi Windows?
Secara umum, pengalaman saya menemukan bahwa menyimpan jalur lebih murah untuk bisnis bahkan memperhitungkan kurangnya ACID dan kemungkinan anak yatim. Namun, itu tidak berarti bahwa internet tidak banyak dengan cerita-cerita tentang kurangnya kontrol ACID yang salah dengan penyimpanan file tetapi itu berarti bahwa secara umum solusi itu lebih mudah untuk dibangun, dipahami dan dipelihara.
sumber
Dalam banyak kasus, ini adalah ide yang buruk. Ini akan menggembungkan file database dan menyebabkan beberapa masalah kinerja. Jika Anda menempelkan gumpalan di sebuah meja dengan sejumlah besar kolom itu bahkan lebih buruk.
Namun! Beberapa database, seperti SQL Server memiliki tipe kolom FILESTREAM. Dalam hal ini, data Anda sebenarnya disimpan dalam file terpisah di server database dan hanya ID untuk file yang disimpan dalam tabel. Dalam hal ini saya tidak melihat banyak alasan untuk tidak menyimpan data di server SQL. File secara otomatis dimasukkan sebagai bagian dari cadangan server, dan database serta file tidak pernah tidak sinkron. Masalah dengan saran Tony untuk menyimpan nama file, adalah bahwa database dan sistem file dapat tidak sinkron. Basis data akan mengklaim file ada ketika sudah dihapus pada disk. Jika suatu proses memodifikasi database dan kemudian crash, file dan database tidak akan cocok (yaitu tidak ada ACID dengan file di luar database).
sumber
Ya, itu adalah praktik yang buruk.
Dampak kinerja pada DB:
SELECT
dengan kolom BLOB, Anda akan selalu melakukan akses disk, sementara tanpa BLOB Anda memiliki kesempatan untuk mendapatkan data langsung dari RAM (DB throughput tinggi akan dioptimalkan agar sesuai dengan tabel dalam RAM);Keuntungan kecepatan - tidak ada ! Sementara beberapa filesystem lama tidak akan menangani direktori dengan jutaan file, sebagian besar modern tidak memiliki masalah sama sekali dan bahkan menggunakan jenis struktur data yang sama seperti BD (biasanya B-tree). Misalnya ext4 (sistem file Linux standar) menggunakan Htree .
Kesimpulan: itu akan menghambat kinerja DB Anda dan tidak akan meningkatkan kinerja pengambilan file.
Juga, karena Anda berbicara tentang aplikasi web - melayani file statis langsung dari sistem file menggunakan server web modern, yang dapat melakukan
sendfile()
syscall adalah peningkatan kinerja yang luar biasa . Ini tentu saja tidak mungkin jika Anda mengambil file dari DB. Pertimbangkan misalnya benchmark ini , menunjukkan Ngnix melakukan 25K req / s dengan 1000 koneksi bersamaan pada laptop low-end. Beban semacam itu akan menggoreng jenis DB apa pun.sumber
Saya akan pragmatis tentang hal itu, dan mengikuti prinsip "jangan optimalkan". Buat solusi yang masuk akal saat ini, dan yang Anda punya sumber daya pengembangan untuk diimplementasikan dengan benar. Ada banyak masalah potensial . Tetapi itu tidak selalu menjadi masalah nyata. Misalnya, mungkin tidak akan menjadi masalah jika Anda memiliki 100 pengguna. Ini mungkin menjadi masalah jika Anda memiliki 100.000 atau 10.000.000 pengguna. Tetapi dalam kasus terakhir, harus ada dasar untuk sumber daya pembangunan lebih banyak untuk menangani semua masalah.
Tetapi menyimpan data dalam database tidak membebaskan Anda dari berurusan dengan masalah lain, misalnya di mana file harus disimpan, bagaimana mereka harus didukung, dll. Karena Anda menulis aplikasi web itu akan menjadi ide yang sangat bagus untuk alasan keamanan untuk memastikan bahwa proses hosting aplikasi tidak memiliki akses tulis ke sistem file, jadi Anda perlu mengkonfigurasi server agar proses tersebut memiliki akses baca / tulis ke folder tempat data disimpan.
Saya pribadi akan memilih untuk menyimpan data dalam database, tetapi pastikan bahwa BLOBS tidak dibaca sampai mereka benar-benar diperlukan, yaitu tidak ada "SELECT * FROM ..." dieksekusi pada tabel yang berisi blog. Dan saya akan memastikan bahwa desain membuatnya mudah untuk memindahkan data dari database, ke sistem file, jika Anda mendapatkan masalah kinerja. Misalnya menyimpan informasi file dalam tabel File terpisah , sehingga menjaga informasi file dari entitas bisnis lain.
Dengan asumsi bahwa Anda memiliki kelas File untuk mewakili file yang dibaca di dalam basis data, maka dampak pengkodean untuk memindahkannya nanti akan menjadi minimal.
sumber
Microsoft merilis buku putih tentang ini beberapa tahun yang lalu. Itu berkonsentrasi pada SqlServer, tetapi Anda mungkin menemukan beberapa informasi menarik di sana:
Versi kesimpulan mereka yang sangat ringkas adalah:
Saya akan merekomendasikan Anda menulis beberapa tes kecil untuk use case khusus Anda. Ingatlah bahwa Anda harus waspada terhadap efek caching. (Saya kagum saat pertama kali saya mendapatkan kecepatan simpan ke disk yang tampaknya memiliki throughput yang lebih tinggi daripada yang dimungkinkan secara fisik!)
sumber
Kebijaksanaan konvensional lama untuk menyimpan file di luar basis data mungkin tidak lagi berlaku. Sebagai prinsip, saya lebih menyukai integritas daripada kecepatan, dan dengan DBMS modern, Anda dapat memiliki keduanya.
Tom Kyte tampaknya setuju :
sumber
Iya.
Jika Anda menyajikan file dari sistem file Anda, server Web Anda dapat menggunakan kode kernel seperti sendfile () di BSD atau Linux untuk menyalin file secara langsung ke soket. Ini sangat cepat dan sangat efisien.
Melayani file dari database berarti Anda harus menyalin data dari disk server database ke memori server database, kemudian dari memori server db ke port jaringan server db, lalu masuk dari jaringan ke proses server Web Anda, kemudian keluar lagi ke koneksi jaringan keluar.
Kecuali Anda memiliki alasan yang sangat bagus untuk tidak melakukannya, selalu lebih baik untuk menyajikan file statis dari sistem file.
sumber
Tom Kyte terkenal telah menulis bahwa mereka (Oracle) menggunakan database Oracle sebagai server file dan bekerja dengan sangat baik, bahkan lebih cepat dari sistem file normal, dengan transaksionalitas penuh, tanpa kehilangan kinerja dan dengan cadangan tunggal.
Ya, tetapi perhatikan, mereka adalah produsen Oracle DB, dan untuk pengguna lain ada masalah biaya. Menggunakan DB komersial seperti Oracle untuk penyimpanan file tidak efektif dari segi biaya.
Namun, dengan PostgreSQL misalnya, Anda bisa menjalankan contoh DB lain hanya untuk penyimpanan gumpalan. Kemudian Anda memiliki dukungan transaksional penuh. Tetapi transaksionalitas membutuhkan ruang DB. Ada kebutuhan untuk database untuk menyimpan beberapa contoh gumpalan untuk beberapa transaksi bersamaan. Pada PostgreSQL ini adalah yang paling menyakitkan, karena database ini menyimpan duplikat gumpalan yang dibuat untuk transaksi disimpan bahkan jika mereka tidak diperlukan lagi, sampai proses VACUUM dilakukan.
Dengan penyimpanan sistem file, di sisi lain, Anda harus sangat berhati-hati ketika seseorang memodifikasi file, karena transaksi dapat dibatalkan dan salinan file harus disimpan sampai versi lama tidak lagi terlihat.
Dalam sistem di mana file hanya ditambahkan dan dihapus, dan akses transaksional ke file tidak menjadi masalah, penyimpanan sistem file akan menjadi IMHO pilihan terbaik.
sumber
Biasanya yang terbaik untuk menyimpan BLOB besar di tabel terpisah dan simpan referensi kunci asing ke BLOB di tabel utama Anda. Dengan begitu, Anda masih dapat mengambil file dari database (sehingga Anda tidak memerlukan kode khusus) dan Anda menghindari masalah seputar dependensi DB eksternal (menjaga DB dan filesystem dalam sinkronisasi, dll), tetapi Anda hanya dikenakan overhead itu jika Anda secara eksplisit bergabung ke tabel itu (atau melakukan panggilan terpisah). 10MB tidak terlalu besar, kebanyakan database komersial modern tidak akan memiliki masalah. Satu-satunya alasan saya menyimpan file di sistem file adalah untuk mengurangi bandwidth database. Jika database Anda akan mengocok banyak file-file ini, maka Anda mungkin perlu membagi beban kerja dan hanya menyimpan deskriptor file. Kemudian Anda dapat memiliki panggilan terpisah untuk memuat file dari server lain,
sumber
Anda mungkin mengalami beberapa masalah ini:
SELECT *
yang melibatkan deretan dengan gumpalan besar memakan waktu sangat lama, bahkan jika Anda tidak memerlukan gumpalan (Tentu saja Anda harus melakukan pemilihan tertentu, tetapi terkadang aplikasi ditulis seperti ini)Tentu saja Anda juga mendapatkan beberapa manfaat:
Secara pribadi saya tidak melakukannya karena saya menemukan kontra jauh lebih berat daripada pro. Tetapi seperti yang dinyatakan di atas, itu sepenuhnya tergantung pada use case Anda dan semacamnya.
sumber
Beberapa Sistem Manajemen Konten Enterpirse, seperti SiteCore, menggunakan satu database untuk menyimpan data halaman dan database lain untuk menyimpan file. Mereka menggunakan MS SQL Server.
sumber
Untuk implementasi praktis, berikut ini yang perlu Anda perhatikan:
Manfaat:
Kerugian:
sumber