Apakah panggilan basis data benar-benar signifikan dengan panggilan jaringan untuk API web?

16

Di salah satu majikan saya, kami mengerjakan API REST (tetapi juga berlaku untuk SOAP). Klien, yang merupakan UI aplikasi, akan melakukan panggilan melalui web (LAN dalam penyebaran produksi biasa) ke API. API akan melakukan panggilan ke basis data.

Satu tema yang berulang dalam diskusi kami adalah kinerja: beberapa orang di tim percaya bahwa Anda tidak boleh memiliki beberapa panggilan basis data (biasanya dibaca) dari satu panggilan API karena kinerja; Anda harus mengoptimalkannya sehingga setiap panggilan API hanya memiliki (tepatnya) satu panggilan basis data.

Tetapi apakah itu benar-benar penting? Pertimbangkan bahwa UI harus membuat panggilan jaringan ke API; itu cukup besar (urutan besarnya milidetik). Database dioptimalkan untuk menjaga hal-hal dalam memori dan mengeksekusi membaca sangat, sangat cepat (mis. SQL Server memuat dan menyimpan semuanya dalam RAM dan mengkonsumsi hampir semua RAM gratis Anda jika bisa).

TLDR: Apakah benar-benar penting untuk khawatir tentang beberapa panggilan basis data ketika kita sudah melakukan panggilan jaringan melalui LAN? Jika demikian, mengapa?

Untuk lebih jelas, saya berbicara tentang urutan besarnya - Saya tahu bahwa itu tergantung pada spesifikasi (perangkat keras mesin, pilihan API dan DB, dll.) Jika saya memiliki panggilan yang membutuhkan O (milidetik), apakah mengoptimalkan untuk DB panggilan yang mengurangi urutan besarnya, sebenarnya penting? Atau ada lebih banyak masalah daripada ini?

Sunting: untuk anak cucu, saya pikir cukup konyol untuk membuat klaim bahwa kita perlu meningkatkan kinerja dengan menggabungkan panggilan basis data dalam kondisi ini - terutama dengan kurangnya profil. Namun, itu bukan keputusan saya apakah kami melakukan ini atau tidak; Saya ingin tahu apa alasan di balik berpikir ini adalah cara yang benar untuk mengoptimalkan panggilan API web.

ashes999
sumber
Apakah tidak ada panggilan jaringan lain antara lapisan API dan database?
Tanda
4
Apa yang ditunjukkan tes waktu Anda?
Dan Pichelman
@Sign Tidak ada panggilan jaringan antara API dan DB. Mereka dijamin berada di mesin yang sama, dari apa yang saya mengerti.
ashes999
@DanPichelman itulah yang saya tanyakan juga. Sepertinya tidak ada yang mengambil dan mengukur waktu kinerja; kami hanya mendapatkan persyaratan untuk "memperbaiki kinerja dalam X dengan menggabungkan semua panggilan DB menjadi satu panggilan."
ashes999

Jawaban:

25

Tetapi apakah itu benar-benar penting? Pertimbangkan bahwa UI harus membuat panggilan jaringan ke API; itu cukup besar (urutan besarnya milidetik). Database dioptimalkan untuk menjaga hal-hal dalam memori dan mengeksekusi membaca sangat, sangat cepat (mis. SQL Server memuat dan menyimpan semuanya dalam RAM dan mengkonsumsi hampir semua RAM gratis Anda jika bisa).

Logika

Secara teori, Anda benar. Namun, ada beberapa kelemahan dengan alasan ini:

  1. Dari apa yang Anda nyatakan, tidak jelas apakah Anda benar-benar menguji / membuat profil aplikasi Anda. Dengan kata lain, apakah Anda benar - benar tahu bahwa transfer jaringan dari aplikasi ke API adalah komponen yang paling lambat? Karena itu intuitif, mudah untuk menganggap itu. Namun, ketika membahas kinerja, Anda tidak boleh berasumsi. Di perusahaan saya, saya yang memimpin kinerja. Ketika saya pertama kali bergabung, orang-orang terus berbicara tentang CDN, replikasi, dll berdasarkan intuisi tentang apa yang harus menjadi hambatan. Ternyata, masalah kinerja terbesar kami adalah kueri basis data yang berkinerja buruk.

  2. Anda mengatakan bahwa karena basis data bagus dalam mengambil data, bahwa basis data harus berjalan pada kinerja puncak, digunakan secara optimal, dan tidak ada yang dapat dilakukan untuk memperbaikinya. Dengan kata lain, database dirancang untuk menjadi cepat, jadi saya tidak perlu khawatir tentang hal itu. Garis pemikiran berbahaya lainnya. Itu seperti mengatakan mobil dimaksudkan untuk bergerak cepat, jadi saya tidak perlu mengganti oli.

  3. Cara berpikir ini mengasumsikan satu proses pada satu waktu, atau dengan kata lain, tanpa konkurensi. Diasumsikan bahwa satu permintaan tidak dapat memengaruhi kinerja permintaan lainnya. Sumber daya dibagikan, seperti disk I / O, bandwidth jaringan, kumpulan koneksi, memori, siklus CPU, dll. Oleh karena itu, mengurangi satu panggilan database menggunakan sumber daya bersama dapat mencegahnya menyebabkan permintaan lain melambat. Ketika saya pertama kali bergabung dengan majikan saya saat ini, manajemen percaya bahwa menyetel kueri basis data 3 detik adalah buang-buang waktu. 3 detik sangat sedikit, mengapa membuang waktu? Bukankah kita akan lebih baik dengan CDN atau kompresi atau yang lainnya? Tetapi jika saya dapat membuat kueri 3 detik berjalan dalam 1 detik, katakanlah dengan menambahkan indeks, yaitu 2/3 lebih sedikit pemblokiran, 2/3 lebih sedikit waktu yang dihabiskan untuk menempati utas, dan yang lebih penting, lebih sedikit data yang dibaca dari disk,

Teori

Ada konsep umum bahwa kinerja perangkat lunak hanya tentang kecepatan .

Dari perspektif kecepatan murni, Anda benar. Suatu sistem hanya secepat komponennya yang paling lambat. Jika Anda telah membuat profil kode Anda dan menemukan bahwa Internet adalah komponen yang paling lambat, maka yang lainnya jelas bukan bagian yang paling lambat.

Namun, mengingat hal di atas, saya harap Anda dapat melihat bagaimana pertentangan sumber daya, kurangnya pengindeksan, kode yang ditulis dengan buruk, dll. Dapat menciptakan perbedaan kinerja yang mengejutkan.

Asumsinya

Satu hal terakhir. Anda menyebutkan bahwa panggilan basis data harus murah dibandingkan dengan panggilan jaringan dari aplikasi ke API. Tetapi Anda juga menyebutkan bahwa aplikasi dan server API berada di LAN yang sama. Karena itu, bukankah keduanya sebanding dengan panggilan jaringan? Dengan kata lain, mengapa Anda mengasumsikan bahwa transfer API adalah urutan besarnya lebih lambat daripada transfer basis data ketika mereka berdua memiliki bandwidth yang tersedia yang sama? Tentu saja protokol dan struktur datanya berbeda, saya mengerti, tetapi saya membantah anggapan bahwa mereka adalah urutan besarnya berbeda.

Di mana itu mendapat murkey

Seluruh pertanyaan ini adalah tentang panggilan basis data "banyak" versus "tunggal". Tetapi tidak jelas berapa banyak yang multipel. Karena apa yang saya katakan di atas, sebagai aturan umum, saya sarankan membuat panggilan database sesedikit mungkin. Tapi itu hanya aturan praktis.

Inilah alasannya:

  1. Database hebat dalam membaca data. Mereka adalah mesin penyimpanan. Namun, logika bisnis Anda tinggal di aplikasi Anda. Jika Anda membuat aturan bahwa setiap panggilan API menghasilkan tepat satu panggilan basis data, maka logika bisnis Anda mungkin berakhir di basis data. Mungkin itu baik-baik saja. Banyak sistem melakukan itu. Tetapi beberapa tidak. Ini tentang fleksibilitas.
  2. Terkadang untuk mencapai decoupling yang baik, Anda ingin memisahkan 2 panggilan basis data. Misalnya, mungkin setiap permintaan HTTP dialihkan melalui filter keamanan umum yang memvalidasi dari DB bahwa pengguna memiliki hak akses yang tepat. Jika ya, lanjutkan untuk menjalankan fungsi yang sesuai untuk URL itu. Fungsi itu dapat berinteraksi dengan database.
  3. Memanggil basis data dalam satu lingkaran. Inilah mengapa saya bertanya berapa banyak yang multipel. Dalam contoh di atas, Anda akan memiliki 2 panggilan basis data. 2 baik-baik saja. 3 mungkin baik-baik saja. N tidak baik. Jika Anda memanggil basis data dalam satu lingkaran, Anda sekarang telah membuat kinerja linier, yang berarti akan lebih lama semakin banyak yang ada dalam input loop. Jadi dengan tegas mengatakan bahwa waktu jaringan API adalah yang paling lambat benar-benar mengabaikan anomali seperti 1% dari lalu lintas Anda memerlukan waktu lama karena loop belum ditemukan yang memanggil database 10.000 kali.
  4. Terkadang ada beberapa hal yang lebih baik di aplikasi Anda, seperti beberapa perhitungan yang rumit. Anda mungkin perlu membaca beberapa data dari database, melakukan beberapa perhitungan, kemudian berdasarkan hasil, meneruskan parameter ke panggilan database kedua (mungkin untuk menulis beberapa hasil). Jika Anda menggabungkannya menjadi satu panggilan (seperti prosedur tersimpan) hanya untuk memanggil basis data sekali saja, Anda telah memaksakan diri untuk menggunakan basis data untuk sesuatu yang mungkin lebih baik digunakan oleh server aplikasi.
  5. Load balancing: Anda memiliki 1 database (mungkin) dan beberapa server aplikasi yang seimbang. Oleh karena itu, semakin banyak pekerjaan yang dilakukan aplikasi dan semakin sedikit basis data, semakin mudah untuk mengukur karena umumnya lebih mudah untuk menambahkan server aplikasi daripada membuat replikasi database. Berdasarkan poin-poin sebelumnya, mungkin masuk akal untuk menjalankan kueri SQL, kemudian melakukan semua perhitungan dalam aplikasi, yang didistribusikan di beberapa server, dan kemudian menulis hasilnya setelah selesai. Ini bisa memberikan hasil yang lebih baik (bahkan jika keseluruhan waktu transaksi adalah sama).

TL; DR

TLDR: Apakah benar-benar penting untuk khawatir tentang beberapa panggilan basis data ketika kita sudah melakukan panggilan jaringan melalui LAN? Jika demikian, mengapa?

Ya, tetapi hanya sampai batas tertentu. Anda harus mencoba meminimalkan jumlah panggilan basis data saat praktis, tetapi jangan gabungkan panggilan yang tidak ada hubungannya satu sama lain hanya untuk menggabungkannya. Juga, hindari memanggil basis data dalam satu lingkaran di semua biaya.

Brandon
sumber
3

Sepertinya tim Anda mengoptimalkan sebelum mereka punya alasan untuk itu. Sudahkah Anda mengukur waktu untuk melaksanakan permintaan ini? Peluang yang memaksa paradigma ini akan menciptakan kinerja yang lebih buruk bagi pengguna akhir karena perjalanan pulang-pergi ke server web akan memiliki latensi yang jauh lebih tinggi daripada waktu koneksi dari server web ke database. Selain itu, sebagian besar peramban web hanya akan membuat 2 koneksi bersamaan ke satu server web, jadi untuk laman yang rumit, Anda mungkin akan menemui hambatan di sana.

Either way, keputusan optimasi tidak boleh dibuat tanpa data untuk mendukungnya. Ukur dan temukan yang terbaik untuk aplikasi Anda.

brianfeucht
sumber
1
Ini adalah komentar yang bagus tentang praktik kinerja kami yang buruk, tetapi tidak menjawab pertanyaan saya tentang apakah panggilan DB adalah sesuatu yang perlu dikhawatirkan ketika saya sudah memiliki panggilan jaringan.
ashes999
1
Secara umum, saya telah menemukan membuat beberapa panggilan basis data tidak menjadi masalah. Ini sebagian besar karena pooling koneksi dan latensi kecil antara DB dan server web. Ada titik di mana membuat banyak panggilan db yang berbeda akan berdampak negatif pada kinerja, tetapi saya tidak memiliki nomor yang sulit untuk Anda. Itu semua tergantung pada lingkungan dan aplikasi. Hanya mengukur yang akan memberi Anda jawaban yang Anda cari.
brianfeucht
Seharusnya (harus) tidak tergantung pada spesifik, karena saya berbicara tentang urutan besarnya.
ashes999
Hanya tebakan kasar (Anda perlu mengukur): Rata-rata waktu untuk terhubung ke DB dari Web Server: 2ms Rata-rata waktu untuk terhubung ke Web Server dari Klien: 20ms Jadi dengan asumsi angka-angka itu saya secara acak menarik keluar dari udara sudah benar, Anda bisa melakukan 10 panggilan basis data dalam waktu yang diperlukan untuk melakukan satu panggilan layanan web. Dengan asumsi bahwa permintaan basis data mengambil jumlah waktu yang sama. Angka-angka itu sangat tergantung pada lingkungan. Jika klien membuat panggilan layanan web adalah lokal, ia dapat menurunkannya dengan beberapa kali lipat.
brianfeucht
2

Kami tidak bisa memberi tahu Anda.

Kami tidak melihat seperti apa pertanyaan Anda. Kami tidak tahu berapa lama waktu yang dibutuhkan untuk menyelesaikannya. Kami tidak tahu berapa banyak overhead yang terlibat dalam setiap permintaan ke server API Anda. Kami tidak tahu seberapa tersebar klien Anda secara geografis. Dll

Jika ini adalah skenario yang memerlukan pengoptimalan dan merupakan salah satu di mana Anda dapat memutuskan apakah akan membagi atau menggabungkan panggilan, Anda perlu membandingkannya dengan dua cara : Tentukan untuk apa Anda mengoptimalkan (latensi UI, beban server CPU, pertengkaran, dll.) dan pilih salah satu yang lebih baik mencapai sasaran pengoptimalan Anda.


Selain itu, satu-satunya satu hal yang saya dapat menambahkan dengan pasti relatif ini:

Dalam satu permintaan, Anda harus melakukan semua pertanyaan yang perlu Anda lakukan untuk membangun respons.

Dengan kata lain, jika respons tidak dapat dihasilkan sampai semua N query dilakukan, biasanya tidak masuk akal untuk memisahkannya. Jika Anda dapat menghasilkan hasil yang bermakna, baik peralihan atau selesai, setelah setiap kueri, mulai membuat tolok ukur.

svidgen
sumber
1

Dua pemikiran:

Pertama, kepada konsumen yang menggunakan API, ia melakukan satu panggilan untuk menyelesaikan tugas. Apa yang terjadi setelah server Anda menerima panggilan untuk mengisi permintaan tidak boleh terlalu kaku. Jika satu panggilan dari konsumen membutuhkan 10 item sub-kerja untuk mengumpulkan data dan mengembalikannya, maka itu harus diterima.

Kedua: Apakah Anda melihat masalah kinerja database aktual dengan proses yang dimaksud? Pengalaman saya menunjukkan bahwa sering mencoba memasukkan semua aspek permintaan basis data ke dalam satu panggilan tunggal dapat menghasilkan panggilan yang kurang efisien daripada hanya membuat tiga atau empat panggilan untuk data. Database modern sangat efisien dalam caching dan rencana eksekusi. Seringkali, ketika Anda mencoba untuk melakukan terlalu banyak Anda akan melihat prosedur dengan kursor (sangat buruk untuk kinerja karena data bertindak secara baris demi baris, bukan sebagai satu set sekaligus) dan kode yang menghasilkan rencana yang kurang efisien daripada jika Anda telah melanggar panggilan menjadi beberapa langkah mudah kecil.

Di luar pengaturan kode yang sederhana, saya setuju bahwa setiap panggilan API mungkin harus memanggil prosedur tersimpan tunggal (atau fungsi db) yang pada gilirannya bertanggung jawab untuk mengisi permintaan. Mungkin ada lebih dari satu langkah dalam prosedur.

Richard
sumber
Saya setuju dengan Anda tentang pengukuran kinerja, yang tampaknya tidak dilakukan siapa pun. Tidak ada bukti bahwa ini lebih cepat, tetapi terus saja muncul. Kinerja muncul sebagai masalah ketika kami memiliki beberapa panggilan yang dapat membuat, katakanlah, 1000 DB SELECT.
ashes999
@ ashes999 sementara Anda mungkin mendapatkan kecepatan melihat jumlah panggilan db, itu lebih mungkin ditemukan dalam strategi pengindeksan dll. bukan jumlah panggilan. Seperti yang ditunjukkan semua orang, lihat data kinerja.
Richard
Richard, aku setuju, dan aku benar-benar tahu itu. Pertanyaan saya adalah mengapa berbagai orang terus mengemukakan hal ini bahwa "beberapa panggilan DB lambat" ketika ada panggilan jaringan yang terlibat. Saya benar-benar tidak melihat bagaimana itu bisa signifikan.
ashes999
@ ashes999 Maaf, mungkin Anda harus masuk ke sedikit lebih detail tentang panggilan jaringan, karena itu tampak jelas, saya rasa ada sedikit lebih banyak untuk pertanyaan Anda. Saya merasa kami kehilangan sesuatu dalam pertanyaan Anda. Anda akan selalu mengalami latensi jaringan, dan setiap panggilan berpotensi meningkat sebanyak "x" kali untuk setiap panggilan (dalam istilah sederhana). Pernyataan pada nilai nominal adalah benar, beberapa panggilan jaringan akan lebih lambat dari satu panggilan jaringan ke db. Itu sebabnya saya menyarankan satu panggilan ke prosedur tersimpan, kemudian, yang dapat membuat beberapa panggilan ke db tanpa panggilan multi-jaringan.
Richard
1

Jika basis data ada di server yang berbeda dari layanan REST Anda, setiap panggilan basis data akan menghasilkan bolak-balik jaringan dan itu dapat sangat merusak kinerja:

Saya pernah mengamati satu panggilan layanan web diterjemahkan ke sekitar 500 permintaan basis data - ini bukan masalah ketika layanan web dan basis data terletak pada mesin yang sama, tetapi berubah menjadi waktu respons 6-7 detik ketika mereka berada di berbeda mesin.

Jelas, 500 perjalanan pulang pergi ke basis data cukup ekstrem. Saya tidak yakin apa persyaratan kinerja Anda, tetapi sebagai aturan praktis saya akan mengatakan bahwa jika Anda tetap di bawah sekitar 10 permintaan basis data per panggilan-REST Anda tidak akan mengalami hit kinerja yang signifikan.

Astrotrain
sumber
1

Kami memiliki beberapa aplikasi yang sangat, sangat cerewet. Ada panggilan basis data untuk setiap. Tunggal. Sedikit. Benda. Melayani data referensi berulang kali adalah bagian utama dari beban kerja pada sistem. Semua penjadwalan thread pekerja, memperoleh dan menjatuhkan kunci, memeriksa rencana cache dll menambahkan bahkan jika tidak ada IO disk yang sebenarnya. Pertentangan lebih tinggi karena transaksi harus menahan kunci di beberapa panggilan DB dan karenanya throughput jauh lebih rendah daripada yang seharusnya. Tim-tim itu sekarang melihat harus membeli server DB yang baru dan sangat mahal karena hal ini.

Jadi, meskipun sebagian besar waktu yang berlalu dalam konfigurasi sistem Anda saat ini diambil dengan panggilan REST API, mengabaikan kinerja di tingkat DB menyimpan masalah untuk masa depan.

Michael Green
sumber
0

Jalur optimasi yang disajikan hanyalah cara yang salah untuk melihat sesuatu.

Panggilan API harus berupa atom. Dengan kata lain, saya harus dapat membuat 1 panggilan web API untuk melakukan tindakan yang saya inginkan. Apakah itu untuk mengambil data, memperbarui catatan atau apa pun. Seharusnya TIDAK PERNAH mengambil lebih dari 1 panggilan untuk menyebabkan tindakan. Dan mencoba untuk meningkatkan transaksi di beberapa panggilan harus dijauhi seperti wabah.

Terkadang satu tindakan agak rumit. Misalnya, mengambil data yang digabungkan dari beberapa sumber: sekali lagi, ini harus menjadi satu panggilan. Entah semuanya bekerja atau semuanya gagal.

Sekarang, mengatakan bahwa panggilan API tunggal seharusnya hanya mengeksekusi satu permintaan DB agak bodoh. Seperti yang telah Anda tunjukkan, biaya overhead untuk membuat panggilan di seluruh jaringan sering kali lebih mahal dalam hal waktu keseluruhan.

Saya agak bisa memahami pernyataan mereka bahwa satu query berjalan dapat lebih cepat daripada beberapa; tetapi ini memberikan kesan yang salah karena mengabaikan total DB dan beban jaringan. Hanya dengan membuat profil berbagai cara untuk menarik data dari DB, Anda dapat mengetahui apa masalahnya sebenarnya. Saya yakin semua orang memiliki cerita di mana permintaan tertentu dieksekusi 100 kali lebih sering daripada yang diperkirakan membunuh sistem sampai indeks yang tepat diberlakukan ...

Pada akhirnya Anda tidak akan bisa meyakinkan mereka hanya dengan bicara. Buat test case untuk pendekatan dan profil mereka. Perhatikan total waktu untuk memperoleh data yang Anda butuhkan, jumlah lalu lintas jaringan yang dihasilkan, jumlah dan waktu panggilan basis data, dll. Ambil pendekatan holistik - artinya Anda melihat keseluruhan sistem - dan Anda harus memiliki banyak data untuk memakan gagak atau menunjukkan kepada mereka jalur emas.

Bukan saya
sumber