Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Hello, Habr! Saya membentangkan kepada anda terjemahan artikel
"Bagaimana pangkalan data hubungan berfungsi".

Apabila ia datang kepada pangkalan data hubungan, saya tidak dapat membantu tetapi berfikir ada sesuatu yang hilang. Mereka digunakan di mana-mana. Terdapat banyak pangkalan data berbeza yang tersedia, daripada SQLite yang kecil dan berguna kepada Teradata yang berkuasa. Tetapi terdapat hanya beberapa artikel yang menerangkan cara pangkalan data berfungsi. Anda boleh mencari sendiri menggunakan "howdoesarelationaldatabasework" untuk melihat betapa sedikit hasil yang terdapat. Lebih-lebih lagi, artikel ini pendek. Jika anda sedang mencari teknologi buzzy terkini (BigData, NoSQL atau JavaScript), anda akan temui lebih banyak artikel mendalam yang menerangkan cara ia berfungsi.

Adakah pangkalan data hubungan terlalu lama dan terlalu membosankan untuk dijelaskan di luar kursus universiti, kertas penyelidikan dan buku?

Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Sebagai pembangun, saya tidak suka menggunakan sesuatu yang saya tidak faham. Dan jika pangkalan data telah digunakan selama lebih daripada 40 tahun, mesti ada sebabnya. Selama bertahun-tahun, saya telah menghabiskan beratus-ratus jam untuk benar-benar memahami kotak hitam pelik yang saya gunakan setiap hari. Pangkalan Data Hubungan sangat menarik kerana mereka berdasarkan konsep yang berguna dan boleh diguna semula. Jika anda berminat untuk memahami pangkalan data, tetapi tidak pernah mempunyai masa atau kecenderungan untuk mendalami topik yang luas ini, anda harus menikmati artikel ini.

Walaupun tajuk artikel ini jelas, tujuan artikel ini bukan untuk memahami cara menggunakan pangkalan data... Oleh itu, anda sepatutnya sudah tahu cara menulis permintaan sambungan mudah dan pertanyaan asas JENAYAH; jika tidak, anda mungkin tidak memahami artikel ini. Itu sahaja yang anda perlu tahu, saya akan terangkan selebihnya.

Saya akan mulakan dengan beberapa asas sains komputer, seperti kerumitan masa algoritma (BigO). Saya tahu sesetengah daripada anda membenci konsep ini, tetapi tanpanya anda tidak akan dapat memahami selok-belok dalam pangkalan data. Oleh kerana ini adalah topik yang besar, Saya akan fokus pada apa yang saya rasa penting: bagaimana pangkalan data memproses SQL siasatan. Saya hanya akan memperkenalkan konsep asas pangkalan datasupaya pada akhir artikel anda mempunyai idea tentang apa yang berlaku di bawah tudung.

Memandangkan ini adalah artikel yang panjang dan teknikal yang melibatkan banyak algoritma dan struktur data, luangkan masa anda untuk membacanya. Sesetengah konsep mungkin sukar difahami; anda boleh melangkaunya dan masih mendapat idea umum.

Bagi yang lebih arif dalam kalangan anda, artikel ini dibahagikan kepada 3 bahagian:

  • Gambaran keseluruhan komponen pangkalan data peringkat rendah dan peringkat tinggi
  • Gambaran Keseluruhan Proses Pengoptimuman Pertanyaan
  • Gambaran Keseluruhan Urus Niaga dan Pengurusan Kolam Penampan

Kembali kepada asas

Bertahun-tahun yang lalu (dalam galaksi yang jauh, jauh...), pembangun perlu mengetahui dengan tepat bilangan operasi yang mereka pengekodkan. Mereka mengetahui algoritma dan struktur data mereka dengan teliti kerana mereka tidak mampu membazirkan CPU dan memori komputer mereka yang perlahan.

Dalam bahagian ini, saya akan mengingatkan anda tentang beberapa konsep ini kerana ia penting untuk memahami pangkalan data. Saya juga akan memperkenalkan konsep tersebut indeks pangkalan data.

O(1) lwn O(n2)

Pada masa kini, ramai pembangun tidak mengambil berat tentang kerumitan masa algoritma... dan mereka betul!

Tetapi apabila anda berurusan dengan banyak data (saya tidak bercakap beribu-ribu) atau jika anda bergelut dalam milisaat, menjadi penting untuk memahami konsep ini. Dan seperti yang anda boleh bayangkan, pangkalan data perlu berurusan dengan kedua-dua situasi! Saya tidak akan membuat anda menghabiskan lebih banyak masa daripada yang diperlukan untuk menyampaikan maksud itu. Ini akan membantu kami memahami konsep pengoptimuman berasaskan kos kemudian (kos berdasarkan pengoptimuman).

Konsep

Kerumitan masa algoritma digunakan untuk melihat tempoh masa yang diperlukan untuk melaksanakan algoritma bagi jumlah data tertentu. Untuk menerangkan kerumitan ini, kami menggunakan tatatanda matematik O besar. Tatatanda ini digunakan dengan fungsi yang menerangkan bilangan operasi yang diperlukan oleh algoritma untuk bilangan input tertentu.

Sebagai contoh, apabila saya menyebut "algoritma ini mempunyai kerumitan O(some_function())", ini bermakna algoritma memerlukan operasi some_function(a_certain_amount_of_data) untuk memproses sejumlah data.

Dalam kes ini, Bukan jumlah data yang penting**, jika tidak ** bagaimana bilangan operasi meningkat dengan peningkatan volum data. Kerumitan masa tidak memberikan bilangan operasi yang tepat, tetapi merupakan cara yang baik untuk menganggarkan masa pelaksanaan.

Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Dalam graf ini anda boleh melihat bilangan operasi berbanding jumlah data input untuk pelbagai jenis kerumitan masa algoritma. Saya menggunakan skala logaritma untuk memaparkannya. Dalam erti kata lain, jumlah data meningkat dengan cepat daripada 1 kepada 1 bilion. Kita dapat melihat bahawa:

  • O(1) atau kerumitan malar kekal malar (jika tidak, ia tidak akan dipanggil kerumitan malar).
  • O(log(n)) kekal rendah walaupun dengan berbilion data.
  • Kesukaran paling teruk - O(n2), di mana bilangan operasi berkembang pesat.
  • Dua komplikasi lain meningkat dengan cepat.

contoh

Dengan jumlah data yang kecil, perbezaan antara O(1) dan O(n2) boleh diabaikan. Sebagai contoh, katakan anda mempunyai algoritma yang perlu memproses 2000 elemen.

  • Algoritma O(1) akan dikenakan bayaran 1 operasi
  • Algoritma O(log(n)) akan dikenakan bayaran sebanyak 7 operasi
  • Algoritma O(n) akan dikenakan bayaran sebanyak 2 operasi
  • Algoritma O(n*log(n)) akan menelan kos sebanyak 14 operasi
  • Algoritma O(n2) akan menelan kos sebanyak 4 operasi

Perbezaan antara O(1) dan O(n2) nampaknya besar (4 juta operasi) tetapi anda akan kehilangan maksimum 2 ms, hanya masa untuk berkelip mata. Memang pemproses moden boleh memproses ratusan juta operasi sesaat. Inilah sebabnya mengapa prestasi dan pengoptimuman tidak menjadi isu dalam banyak projek IT.

Seperti yang saya katakan, masih penting untuk mengetahui konsep ini apabila bekerja dengan sejumlah besar data. Jika kali ini algoritma perlu memproses 1 elemen (yang tidak begitu banyak untuk pangkalan data):

  • Algoritma O(1) akan dikenakan bayaran 1 operasi
  • Algoritma O(log(n)) akan dikenakan bayaran sebanyak 14 operasi
  • Algoritma O(n) akan dikenakan bayaran sebanyak 1 operasi
  • Algoritma O(n*log(n)) akan menelan kos sebanyak 14 operasi
  • Algoritma O(n2) akan dikenakan bayaran sebanyak 1 operasi

Saya belum membuat pengiraan, tetapi saya akan mengatakan bahawa dengan algoritma O(n2) anda mempunyai masa untuk minum kopi (walaupun dua!). Jika anda menambah 0 lagi pada volum data, anda akan mempunyai masa untuk tidur sebentar.

Mari kita pergi lebih dalam

Untuk maklumat anda:

  • Carian jadual hash yang baik menemui elemen dalam O(1).
  • Mencari pokok yang seimbang menghasilkan keputusan dalam O(log(n)).
  • Mencari tatasusunan menghasilkan keputusan dalam O(n).
  • Algoritma pengisihan terbaik mempunyai kerumitan O(n*log(n)).
  • Algoritma pengisihan yang buruk mempunyai kerumitan O(n2).

Nota: Dalam bahagian berikut kita akan melihat algoritma dan struktur data ini.

Terdapat beberapa jenis kerumitan masa algoritma:

  • senario kes purata
  • senario kes terbaik
  • dan senario kes terburuk

Kerumitan masa selalunya merupakan senario kes terburuk.

Saya hanya bercakap tentang kerumitan masa algoritma, tetapi kerumitan juga digunakan untuk:

  • penggunaan memori algoritma
  • algoritma penggunaan I/O cakera

Sudah tentu, terdapat komplikasi yang lebih teruk daripada n2, contohnya:

  • n4: ini dahsyat! Beberapa algoritma yang disebutkan mempunyai kerumitan ini.
  • 3n: ini lebih teruk! Salah satu algoritma yang akan kita lihat di tengah-tengah artikel ini mempunyai kerumitan ini (dan ia sebenarnya digunakan dalam banyak pangkalan data).
  • faktorial n: anda tidak akan mendapat keputusan anda walaupun dengan jumlah data yang kecil.
  • nn: Jika anda menghadapi kerumitan ini, anda harus bertanya pada diri anda sama ada ini benar-benar bidang aktiviti anda...

Nota: Saya tidak memberi anda takrifan sebenar sebutan O besar, hanya idea. Anda boleh membaca artikel ini di Wikipedia untuk definisi sebenar (asimptotik).

MergeSort

Apakah yang anda lakukan apabila anda perlu mengisih koleksi? Apa? Anda memanggil fungsi sort()... Ok, jawapan yang bagus... Tetapi untuk pangkalan data, anda mesti faham bagaimana fungsi sort() ini berfungsi.

Terdapat beberapa algoritma pengisihan yang baik, jadi saya akan memberi tumpuan kepada yang paling penting: merge sort. Anda mungkin tidak faham mengapa pengisihan data berguna sekarang, tetapi anda perlu selepas bahagian pengoptimuman pertanyaan. Selain itu, memahami jenis gabungan akan membantu kami kemudian memahami operasi gabungan pangkalan data biasa yang dipanggil bergabung menyertai (persatuan penggabungan).

Bercantum

Seperti kebanyakan algoritma yang berguna, isihan cantum bergantung pada helah: menggabungkan 2 tatasusunan diisih bersaiz N/2 ke dalam tatasusunan diisih elemen N hanya memerlukan N operasi. Operasi ini dipanggil penggabungan.

Mari lihat apa maksudnya dengan contoh mudah:

Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Angka ini menunjukkan bahawa untuk membina tatasusunan 8 elemen yang diisih terakhir, anda hanya perlu mengulang sekali pada tatasusunan 2 4 elemen. Oleh kerana kedua-dua tatasusunan 4 elemen telah diisih:

  • 1) anda membandingkan kedua-dua elemen semasa dalam dua tatasusunan (pada permulaan semasa = pertama)
  • 2) kemudian ambil yang terkecil untuk memasukkannya ke dalam tatasusunan 8 elemen
  • 3) dan beralih ke elemen seterusnya dalam tatasusunan di mana anda mengambil elemen terkecil
  • dan ulangi 1,2,3 sehingga anda mencapai elemen terakhir salah satu tatasusunan.
  • Kemudian anda mengambil baki elemen tatasusunan lain untuk meletakkannya ke dalam tatasusunan 8 elemen.

Ini berfungsi kerana kedua-dua tatasusunan 4 elemen diisih dan jadi anda tidak perlu "kembali" dalam tatasusunan tersebut.

Sekarang setelah kita memahami helah itu, inilah pseudokod saya untuk penggabungan:

array mergeSort(array a)
   if(length(a)==1)
      return a[0];
   end if

   //recursive calls
   [left_array right_array] := split_into_2_equally_sized_arrays(a);
   array new_left_array := mergeSort(left_array);
   array new_right_array := mergeSort(right_array);

   //merging the 2 small ordered arrays into a big one
   array result := merge(new_left_array,new_right_array);
   return result;

Merge sort memecahkan masalah kepada masalah yang lebih kecil dan kemudian mencari keputusan masalah yang lebih kecil untuk mendapatkan hasil masalah asal (nota: jenis algoritma ini dipanggil divide and conquer). Jika anda tidak memahami algoritma ini, jangan risau; Saya tidak faham pada kali pertama saya melihatnya. Jika ia boleh membantu anda, saya melihat algoritma ini sebagai algoritma dua fasa:

  • Fasa pembahagian, di mana tatasusunan dibahagikan kepada tatasusunan yang lebih kecil
  • Fasa pengisihan ialah di mana tatasusunan kecil digabungkan (menggunakan kesatuan) untuk membentuk tatasusunan yang lebih besar.

Fasa pembahagian

Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Dalam peringkat pembahagian, tatasusunan dibahagikan kepada tatasusunan unitari dalam 3 langkah. Bilangan langkah rasmi ialah log(N) (sejak N=8, log(N) = 3).

Bagaimana saya tahu ini?

Saya genius! Dalam satu perkataan - matematik. Ideanya ialah setiap langkah membahagikan saiz tatasusunan asal dengan 2. Bilangan langkah ialah bilangan kali anda boleh membahagi tatasusunan asal kepada dua. Ini ialah takrifan tepat bagi logaritma (asas 2).

Fasa menyusun

Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Dalam fasa pengisihan, anda bermula dengan tatasusunan unitari (elemen tunggal). Semasa setiap langkah anda menggunakan berbilang operasi gabungan dan jumlah kos ialah N = 8 operasi:

  • Pada peringkat pertama anda mempunyai 4 gabungan yang menelan kos 2 operasi setiap satu
  • Dalam langkah kedua, anda mempunyai 2 gabungan yang menelan kos 4 operasi setiap satu
  • Dalam langkah ketiga anda mempunyai 1 gabungan yang menelan kos 8 operasi

Oleh kerana terdapat langkah log(N), jumlah kos N * operasi log(N)..

Kelebihan jenis gabungan

Mengapa algoritma ini sangat berkuasa?

Kerana:

  • Anda boleh menukarnya untuk mengurangkan jejak memori supaya anda tidak mencipta tatasusunan baharu tetapi secara langsung mengubah suai tatasusunan input.

Nota: jenis algoritma ini dipanggil in-tempat (mengisih tanpa ingatan tambahan).

  • Anda boleh menukarnya untuk menggunakan ruang cakera dan sejumlah kecil memori pada masa yang sama tanpa menanggung overhed I/O cakera yang ketara. Ideanya adalah untuk memuatkan ke dalam ingatan hanya bahagian yang sedang diproses. Ini penting apabila anda perlu mengisih jadual berbilang gigabait dengan hanya penimbal memori 100 megabait.

Nota: jenis algoritma ini dipanggil jenis luaran.

  • Anda boleh mengubahnya untuk dijalankan pada berbilang proses/benang/pelayan.

Sebagai contoh, isihan gabungan teragih ialah salah satu komponen utama Hadoop (yang merupakan struktur dalam data besar).

  • Algoritma ini boleh menukar plumbum menjadi emas (sungguh!).

Algoritma pengisihan ini digunakan dalam kebanyakan (jika tidak semua) pangkalan data, tetapi ia bukan satu-satunya. Kalau nak tahu lebih lanjut boleh baca ni kerja penyelidikan, yang membincangkan kebaikan dan keburukan algoritma pengisihan pangkalan data biasa.

Jadual Tatasusunan, Pokok dan Hash

Sekarang setelah kita memahami idea kerumitan masa dan pengisihan, saya harus memberitahu anda tentang 3 struktur data. Ini penting kerana mereka adalah asas pangkalan data moden. Saya juga akan memperkenalkan konsep tersebut indeks pangkalan data.

Массив

Tatasusunan dua dimensi ialah struktur data yang paling mudah. Jadual boleh dianggap sebagai tatasusunan. Sebagai contoh:

Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Tatasusunan 2 dimensi ini ialah jadual dengan baris dan lajur:

  • Setiap baris mewakili entiti
  • Lajur menyimpan sifat yang menerangkan entiti.
  • Setiap lajur menyimpan data jenis tertentu (integer, rentetan, tarikh...).

Ini mudah untuk menyimpan dan menggambarkan data, namun, apabila anda perlu mencari nilai tertentu, ini tidak sesuai.

Contohnya, jika anda ingin mencari semua lelaki yang bekerja di UK, anda perlu melihat setiap baris untuk menentukan sama ada baris itu milik UK. Ia akan dikenakan bayaran N transaksiJika N - bilangan baris, yang tidak buruk, tetapi mungkinkah terdapat cara yang lebih pantas? Kini tiba masanya untuk kita berkenalan dengan pokok.

Nota: Kebanyakan pangkalan data moden menyediakan tatasusunan lanjutan untuk menyimpan jadual dengan cekap: jadual tersusun timbunan dan jadual tersusun indeks. Tetapi ini tidak mengubah masalah mencari keadaan tertentu dengan cepat dalam sekumpulan lajur.

Pokok pangkalan data dan indeks

Pokok carian binari ialah pokok binari dengan sifat khas, kunci pada setiap nod mestilah:

  • lebih besar daripada semua kunci yang disimpan dalam subpokok kiri
  • kurang daripada semua kunci yang disimpan dalam subpokok kanan

Mari lihat apa maksud ini secara visual

Idea

Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Pokok ini mempunyai N = 15 unsur. Katakan saya sedang mencari 208:

  • Saya bermula pada akar yang kuncinya ialah 136. Sejak 136<208, saya melihat subpokok kanan nod 136.
  • 398>208 oleh itu saya melihat subpokok kiri nod 398
  • 250>208 oleh itu saya melihat subpokok kiri nod 250
  • 200<208, oleh itu saya melihat subpokok kanan nod 200. Tetapi 200 tidak mempunyai subpokok kanan, nilai tidak wujud (kerana jika ia wujud, ia akan berada di subtree kanan 200).

Sekarang katakan saya sedang mencari 40

  • Saya bermula pada akar yang kuncinya ialah 136. Sejak 136 > 40, saya melihat subpokok kiri nod 136.
  • 80 > 40, oleh itu saya melihat subpokok kiri nod 80
  • 40= 40, nod wujud. Saya mendapatkan semula ID baris di dalam nod (tidak ditunjukkan dalam gambar) dan melihat dalam jadual untuk ID baris yang diberikan.
  • Mengetahui ID baris membolehkan saya mengetahui dengan tepat di mana data berada dalam jadual, jadi saya boleh mendapatkannya serta-merta.

Pada akhirnya, kedua-dua carian akan menyebabkan saya memerlukan bilangan tahap di dalam pokok. Jika anda membaca bahagian tentang pengisihan gabungan dengan teliti, anda harus melihat bahawa terdapat tahap log(N). Kesudahannya, log kos carian(N), boleh tahan!

Mari kita kembali kepada masalah kita

Tetapi ini sangat abstrak, jadi mari kita kembali kepada masalah kita. Daripada integer mudah, bayangkan rentetan yang mewakili negara seseorang dalam jadual sebelumnya. Katakan anda mempunyai pokok yang mengandungi medan "negara" (lajur 3) jadual:

  • Jika anda ingin tahu siapa yang bekerja di UK
  • anda melihat pokok itu untuk mendapatkan nod yang mewakili Great Britain
  • di dalam "UKnode" anda akan menemui lokasi rekod pekerja UK.

Carian ini akan menelan kos operasi log(N) dan bukannya operasi N jika anda menggunakan tatasusunan secara langsung. Apa yang anda baru sampaikan ialah indeks pangkalan data.

Anda boleh membina pepohon indeks untuk mana-mana kumpulan medan (rentetan, nombor, 2 baris, nombor dan rentetan, tarikh...) selagi anda mempunyai fungsi untuk membandingkan kunci (iaitu kumpulan medan) supaya anda boleh menetapkan perintah antara kunci (yang berlaku untuk mana-mana jenis asas dalam pangkalan data).

B+TreeIndex

Walaupun pokok ini berfungsi dengan baik untuk mendapatkan nilai tertentu, terdapat masalah BESAR apabila anda perlukan dapatkan berbilang elemen antara dua nilai. Ini akan menelan kos O(N) kerana anda perlu melihat setiap nod dalam pepohon dan periksa sama ada ia berada di antara kedua-dua nilai ini (cth. dengan traversal tertib pepohon). Selain itu, operasi ini tidak mesra I/O cakera kerana anda perlu membaca keseluruhan pokok. Kita perlu mencari jalan untuk melaksanakan dengan cekap permintaan julat. Untuk menyelesaikan masalah ini, pangkalan data moden menggunakan versi diubah suai bagi pokok sebelumnya yang dipanggil B+Tree. Dalam pokok B+Tree:

  • hanya nod terendah (daun) Menyimpan maklumat (lokasi baris dalam jadual berkaitan)
  • selebihnya nod ada di sini untuk penghalaan ke nod yang betul semasa carian.

Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Seperti yang anda lihat, terdapat lebih banyak nod di sini (dua kali). Sesungguhnya, anda mempunyai nod tambahan, "nod keputusan", yang akan membantu anda mencari nod yang betul (yang menyimpan lokasi baris dalam jadual yang berkaitan). Tetapi kerumitan carian masih O(log(N)) (hanya terdapat satu tahap lagi). Perbezaan besar ialah nod di peringkat bawah disambungkan kepada penggantinya.

Dengan B+Tree ini, jika anda mencari nilai antara 40 dan 100:

  • Anda hanya perlu mencari 40 (atau nilai terdekat selepas 40 jika 40 tidak wujud) seperti yang anda lakukan dengan pokok sebelumnya.
  • Kemudian kumpulkan 40 waris menggunakan pautan waris terus sehingga anda mencapai 100.

Katakan anda menemui pengganti M dan pokok itu mempunyai N nod. Mencari log kos nod tertentu (N) seperti pokok sebelumnya. Tetapi sebaik sahaja anda mendapat nod ini, anda akan mendapat pengganti M dalam operasi M dengan rujukan kepada pengganti mereka. Carian ini hanya berharga M+log(N) operasi berbanding dengan N operasi pada pokok sebelumnya. Selain itu, anda tidak perlu membaca pokok penuh (hanya nod M+log(N)), yang bermaksud kurang penggunaan cakera. Jika M kecil (cth 200 baris) dan N besar (1 baris), akan ada perbezaan BESAR.

Tetapi terdapat masalah baru di sini (sekali lagi!). Jika anda menambah atau memadam baris dalam pangkalan data (dan oleh itu dalam indeks B+Tree yang berkaitan):

  • anda mesti mengekalkan susunan antara nod di dalam B+Tree, jika tidak, anda tidak akan dapat mencari nod di dalam pokok yang tidak diisih.
  • anda mesti mengekalkan bilangan tahap minimum yang mungkin dalam B+Tree, jika tidak, kerumitan masa O(log(N)) menjadi O(N).

Dengan kata lain, B+Tree mestilah teratur dan seimbang. Nasib baik, ini boleh dilakukan dengan operasi memadam dan memasukkan pintar. Tetapi ini memerlukan kos: sisipan dan pemadaman dalam kos pokok B+ O(log(N)). Itulah sebabnya sebahagian daripada anda pernah mendengarnya menggunakan terlalu banyak indeks bukanlah idea yang baik. sungguh, anda memperlahankan memasukkan/kemas kini/padam baris dengan pantas dalam jadualkerana pangkalan data perlu mengemas kini indeks jadual menggunakan operasi O(log(N)) yang mahal untuk setiap indeks. Selain itu, menambah indeks bermakna lebih banyak beban kerja untuk pengurus transaksi (akan diterangkan pada akhir artikel).

Untuk butiran lanjut, anda boleh melihat artikel Wikipedia mengenai B+Tree. Jika anda mahukan contoh pelaksanaan B+Tree dalam pangkalan data, sila lihat artikel ini ΠΈ artikel ini daripada pembangun MySQL terkemuka. Kedua-duanya memberi tumpuan kepada cara InnoDB (enjin MySQL) mengendalikan indeks.

Nota: Seorang pembaca memberitahu saya bahawa, disebabkan pengoptimuman peringkat rendah, pokok B+ harus seimbang sepenuhnya.

Hashtable

Struktur data penting terakhir kami ialah jadual cincang. Ini sangat berguna apabila anda ingin mencari nilai dengan cepat. Selain itu, memahami jadual cincang akan membantu kami kemudian memahami operasi gabungan pangkalan data biasa yang dipanggil gabungan cincang ( hash sertai). Struktur data ini juga digunakan oleh pangkalan data untuk menyimpan beberapa perkara dalaman (cth. kunci meja atau kolam penampan, kita akan melihat kedua-dua konsep ini kemudian).

Jadual cincang ialah struktur data yang cepat mencari elemen dengan kuncinya. Untuk membina jadual hash anda perlu menentukan:

  • kunci untuk elemen anda
  • fungsi hash untuk kunci. Cincang kunci yang dikira memberikan lokasi elemen (dipanggil segmen ).
  • fungsi untuk membandingkan kekunci. Sebaik sahaja anda telah menemui segmen yang betul, anda mesti mencari elemen yang anda cari dalam segmen menggunakan perbandingan ini.

Contoh mudah

Mari kita ambil contoh yang jelas:

Cara Pangkalan Data Perhubungan Berfungsi (Bahagian 1)

Jadual cincang ini mempunyai 10 segmen. Disebabkan saya malas, saya hanya bergambar 5 segmen sahaja, tetapi saya tahu awak bijak, jadi saya biarkan awak bergambar yang 5 lagi itu sendiri. Saya menggunakan fungsi hash modulo 10 kunci. Dalam erti kata lain, saya hanya menyimpan digit terakhir kunci elemen untuk mencari segmennya:

  • jika digit terakhir ialah 0, elemen jatuh ke dalam segmen 0,
  • jika digit terakhir ialah 1, elemen jatuh ke dalam segmen 1,
  • jika digit terakhir ialah 2, elemen jatuh ke dalam kawasan 2,
  • ...

Fungsi perbandingan yang saya gunakan hanyalah kesamaan antara dua integer.

Katakan anda ingin mendapatkan elemen 78:

  • Jadual cincang mengira kod cincang untuk 78, iaitu 8.
  • Jadual cincang melihat segmen 8, dan elemen pertama yang ditemuinya ialah 78.
  • Dia mengembalikan item 78 kepada anda
  • Kos carian hanya 2 operasi (satu untuk mengira nilai cincang dan satu lagi untuk mencari elemen dalam segmen).

Sekarang katakan anda ingin mendapatkan elemen 59:

  • Jadual cincang mengira kod cincang untuk 59, iaitu 9.
  • Jadual cincang mencari dalam segmen 9, elemen pertama ditemui ialah 99. Memandangkan 99!=59, elemen 99 bukan elemen yang sah.
  • Dengan menggunakan logik yang sama, unsur kedua (9), yang ketiga (79), ..., yang terakhir (29) diambil.
  • Elemen tidak ditemui.
  • Pencarian menelan belanja 7 operasi.

Fungsi hash yang baik

Seperti yang anda lihat, bergantung pada nilai yang anda cari, kosnya tidak sama!

Jika saya kini menukar fungsi cincang modulo 1 kunci (iaitu, mengambil 000 digit terakhir), carian kedua hanya memerlukan 000 operasi kerana tiada unsur dalam segmen 6. Cabaran sebenar adalah untuk mencari fungsi cincang yang baik yang akan mencipta baldi yang mengandungi bilangan elemen yang sangat kecil.

Dalam contoh saya, mencari fungsi hash yang baik adalah mudah. Tetapi ini adalah contoh mudah, mencari fungsi cincang yang baik adalah lebih sukar apabila kuncinya ialah:

  • rentetan (contohnya - nama keluarga)
  • 2 baris (contohnya - nama keluarga dan nama pertama)
  • 2 baris dan tarikh (contohnya - nama keluarga, nama pertama dan tarikh lahir)
  • ...

Dengan fungsi cincang yang baik, carian jadual cincang berharga O(1).

Jadual tatasusunan vs cincang

Mengapa tidak menggunakan tatasusunan?

Hmm, soalan yang bagus.

  • Jadual hash boleh sebahagiannya dimuatkan ke dalam ingatan, dan segmen yang tinggal boleh kekal pada cakera.
  • Dengan tatasusunan anda mesti menggunakan ruang bersebelahan dalam ingatan. Jika anda memuatkan meja besar adalah sangat sukar untuk mencari ruang berterusan yang mencukupi.
  • Untuk jadual cincang, anda boleh memilih kunci yang anda mahu (contohnya, negara dan nama keluarga orang).

Untuk maklumat lanjut, anda boleh membaca artikel mengenai JavaPeta Hash, yang merupakan pelaksanaan cekap jadual cincang; anda tidak perlu memahami Java untuk memahami konsep yang diliputi dalam artikel ini.

Sumber: www.habr.com

Tambah komen