Ciri-ciri mereka bentuk model data untuk NoSQL

Pengenalan

Ciri-ciri mereka bentuk model data untuk NoSQL "Anda perlu berlari sepantas yang anda boleh hanya untuk kekal di tempat,
dan untuk ke suatu tempat, anda perlu berlari sekurang-kurangnya dua kali lebih laju!”
(c) Alice in Wonderland

Beberapa ketika dahulu saya diminta memberi syarahan penganalisis syarikat kami mengenai topik mereka bentuk model data, kerana duduk di projek untuk masa yang lama (kadang-kadang selama beberapa tahun) kami terlepas pandang tentang apa yang berlaku di sekeliling kami dalam dunia teknologi IT. Di syarikat kami (kebetulan) banyak projek tidak menggunakan pangkalan data NoSQL (sekurang-kurangnya buat masa ini), jadi dalam kuliah saya, saya secara berasingan memberi perhatian kepada mereka menggunakan contoh HBase dan cuba mengorientasikan penyampaian bahan kepada mereka. yang tidak pernah menggunakannya telah bekerja. Secara khususnya, saya menggambarkan beberapa ciri reka bentuk model data menggunakan contoh yang saya baca beberapa tahun lalu dalam artikel "Pengenalan kepada Reka Bentuk Skema HB ase" oleh Amandeep Khurana. Semasa menganalisis contoh, saya membandingkan beberapa pilihan untuk menyelesaikan masalah yang sama untuk menyampaikan idea utama dengan lebih baik kepada penonton.

Baru-baru ini, "tidak ada apa-apa untuk dilakukan," saya bertanya kepada diri sendiri (hujung minggu Mei yang panjang dalam kuarantin sangat sesuai untuk ini), berapa banyak pengiraan teori akan sepadan dengan amalan? Sebenarnya, ini adalah bagaimana idea untuk artikel ini dilahirkan. Pembangun yang telah bekerja dengan NoSQL selama beberapa hari mungkin tidak mempelajari sesuatu yang baharu daripadanya (dan oleh itu boleh segera melangkau separuh artikel). Tetapi untuk penganalisisBagi mereka yang belum bekerja rapat dengan NoSQL, saya fikir ia berguna untuk mendapatkan pemahaman asas tentang ciri-ciri mereka bentuk model data untuk HBase.

Contoh analisis

Pada pendapat saya, sebelum anda mula menggunakan pangkalan data NoSQL, anda perlu berfikir dengan teliti dan menimbang kebaikan dan keburukan. Selalunya masalah itu berkemungkinan besar boleh diselesaikan menggunakan DBMS hubungan tradisional. Oleh itu, adalah lebih baik untuk tidak menggunakan NoSQL tanpa sebab yang ketara. Jika anda bagaimanapun memutuskan untuk menggunakan pangkalan data NoSQL, maka anda harus mengambil kira bahawa pendekatan reka bentuk di sini agak berbeza. Terutamanya sesetengah daripada mereka mungkin luar biasa bagi mereka yang sebelum ini hanya berurusan dengan DBMS hubungan (menurut pemerhatian saya). Jadi, dalam dunia "hubungan", kita biasanya bermula dengan memodelkan domain masalah, dan hanya kemudian, jika perlu, menyahnormalkan model. Dalam NoSQL kita hendaklah segera mengambil kira senario yang dijangkakan untuk bekerja dengan data dan pada mulanya menyahnormalkan data. Di samping itu, terdapat beberapa perbezaan lain, yang akan dibincangkan di bawah.

Mari kita pertimbangkan masalah "sintetik" berikut, yang mana kita akan terus bekerja:

Ia adalah perlu untuk mereka bentuk struktur storan untuk senarai rakan pengguna beberapa rangkaian sosial abstrak. Untuk memudahkan, kami akan menganggap bahawa semua sambungan kami diarahkan (seperti di Instagram, bukan Linkedin). Struktur harus membolehkan anda dengan berkesan:

  • Jawab soalan sama ada pengguna A membaca pengguna B (corak bacaan)
  • Benarkan menambah/mengalih keluar sambungan sekiranya langganan/penyahlangganan pengguna A daripada pengguna B (templat perubahan data)

Sudah tentu, terdapat banyak pilihan untuk menyelesaikan masalah. Dalam pangkalan data hubungan biasa, kemungkinan besar kami hanya akan membuat jadual perhubungan (mungkin ditunjukkan jika, sebagai contoh, kami perlu menyimpan kumpulan pengguna: keluarga, kerja, dll., yang termasuk "rakan" ini), dan untuk mengoptimumkan kelajuan akses akan menambah indeks/pemisahan. Kemungkinan besar jadual akhir akan kelihatan seperti ini:

user_id
kawan_id

Vasya
Peter

Vasya
Оля

selepas ini, untuk kejelasan dan pemahaman yang lebih baik, saya akan menunjukkan nama dan bukannya ID

Dalam kes HBase, kita tahu bahawa:

  • carian cekap yang tidak menghasilkan imbasan jadual penuh adalah mungkin secara eksklusif dengan kunci
    • sebenarnya, itulah sebabnya menulis pertanyaan SQL yang biasa kepada ramai kepada pangkalan data sedemikian adalah idea yang tidak baik; secara teknikal, sudah tentu, anda boleh menghantar pertanyaan SQL dengan Joins dan logik lain ke HBase dari Impala yang sama, tetapi sejauh manakah ia akan berkesan...

Oleh itu, kami terpaksa menggunakan ID pengguna sebagai kunci. Dan pemikiran pertama saya mengenai topik "di mana dan bagaimana untuk menyimpan ID rakan?" mungkin idea untuk menyimpannya dalam lajur. Pilihan yang paling jelas dan "naif" ini akan kelihatan seperti ini (mari kita panggilnya Pilihan 1 (lalai)untuk rujukan lanjut):

RowKey
Lajur

Vasya
1: Petya
2: Olya
3: Dasha

Peter
1: Masha
2: Vasya

Di sini, setiap baris sepadan dengan satu pengguna rangkaian. Lajur mempunyai nama: 1, 2, ... - mengikut bilangan rakan, dan ID rakan disimpan dalam lajur. Adalah penting untuk ambil perhatian bahawa setiap baris akan mempunyai bilangan lajur yang berbeza. Dalam contoh dalam rajah di atas, satu baris mempunyai tiga lajur (1, 2 dan 3), dan yang kedua hanya mempunyai dua (1 dan 2) - di sini kami sendiri menggunakan dua sifat HBase yang pangkalan data hubungan tidak mempunyai:

  • keupayaan untuk menukar komposisi lajur secara dinamik (tambah rakan -> tambah lajur, alih keluar rakan -> padam lajur)
  • baris yang berbeza mungkin mempunyai komposisi lajur yang berbeza

Mari semak struktur kami untuk pematuhan dengan keperluan tugas:

  • Membaca data: untuk memahami sama ada Vasya melanggan Olya, kita perlu menolak keseluruhan baris dengan kekunci RowKey = "Vasya" dan susun nilai lajur sehingga kita "bertemu" Olya di dalamnya. Atau lelaran melalui nilai semua lajur, "tidak bertemu" Olya dan kembalikan jawapan Salah;
  • Mengedit data: menambah rakan: untuk tugasan yang serupa kita juga perlu tolak keseluruhan baris menggunakan kekunci RowKey = “Vasya” untuk mengira jumlah bilangan rakannya. Kami memerlukan jumlah bilangan rakan ini untuk menentukan bilangan lajur yang kami perlukan untuk menulis ID rakan baharu itu.
  • Menukar data: memadam rakan:
    • Perlu tolak keseluruhan baris dengan kekunci RowKey = “Vasya” dan mengisih lajur untuk mencari yang mana rakan yang hendak dipadamkan direkodkan;
    • Seterusnya, selepas memadamkan rakan, kita perlu "mengalih" semua data ke dalam satu lajur supaya tidak mendapat "jurang" dalam penomboran mereka.

Sekarang mari kita menilai sejauh mana produktif algoritma ini, yang perlu kita laksanakan pada bahagian "aplikasi bersyarat", akan, menggunakan O-simbolisme. Mari kita nyatakan saiz rangkaian sosial hipotesis kita sebagai n. Maka bilangan maksimum rakan yang boleh dimiliki oleh seorang pengguna ialah (n-1). Kita boleh mengabaikan ini (-1) untuk tujuan kita, kerana dalam rangka penggunaan simbol-O ia tidak penting.

  • Membaca data: adalah perlu untuk menolak keseluruhan baris dan melelaran melalui semua lajurnya dalam had. Ini bermakna anggaran atas kos adalah lebih kurang O(n)
  • Mengedit data: menambah rakan: untuk menentukan bilangan rakan, anda perlu mengulangi semua lajur baris, dan kemudian masukkan lajur baharu => O(n)
  • Menukar data: memadam rakan:
    • Sama seperti menambah - anda perlu melalui semua lajur dalam had => O(n)
    • Selepas mengalih keluar lajur, kita perlu "menggerakkannya". Jika anda melaksanakan "head-on" ini, maka dalam had anda memerlukan sehingga (n-1) operasi. Tetapi di sini dan seterusnya dalam bahagian praktikal kita akan menggunakan pendekatan yang berbeza, yang akan melaksanakan "pseudo-shift" untuk bilangan operasi tetap - iaitu, masa yang berterusan akan dibelanjakan untuknya, tanpa mengira n. Masa malar ini (O(2) tepatnya) boleh diabaikan berbanding dengan O(n). Pendekatan ini digambarkan dalam rajah di bawah: kami hanya menyalin data dari lajur "terakhir" ke lajur yang kami mahu memadamkan data, dan kemudian memadamkan lajur terakhir:
      Ciri-ciri mereka bentuk model data untuk NoSQL

Secara keseluruhan, dalam semua senario kami menerima kerumitan pengiraan asimptotik O(n).
Anda mungkin sudah perasan bahawa kami hampir selalu perlu membaca keseluruhan baris daripada pangkalan data, dan dalam dua kes daripada tiga, hanya untuk melalui semua lajur dan mengira jumlah bilangan rakan. Oleh itu, sebagai percubaan untuk pengoptimuman, anda boleh menambah lajur "kira", yang menyimpan jumlah bilangan rakan setiap pengguna rangkaian. Dalam kes ini, kita tidak boleh membaca keseluruhan baris untuk mengira jumlah bilangan rakan, tetapi membaca hanya satu lajur "kiraan". Perkara utama adalah jangan lupa untuk mengemas kini "kiraan" apabila memanipulasi data. Itu. kita bertambah baik Pilihan 2 (kiraan):

RowKey
Lajur

Vasya
1: Petya
2: Olya
3: Dasha
kiraan: 3

Peter
1: Masha
2: Vasya

kiraan: 2

Berbanding dengan pilihan pertama:

  • Membaca data: untuk mendapatkan jawapan kepada soalan "Adakah Vasya membaca Olya?" tiada apa yang berubah => O(n)
  • Mengedit data: menambah rakan: Kami telah memudahkan penyisipan rakan baharu, kerana sekarang kami tidak perlu membaca keseluruhan baris dan mengulangi lajurnya, tetapi hanya boleh mendapatkan nilai lajur "kira", dsb. segera tentukan nombor lajur untuk memasukkan rakan baharu. Ini membawa kepada pengurangan kerumitan pengiraan kepada O(1)
  • Menukar data: memadam rakan: Apabila memadamkan rakan, kami juga boleh menggunakan lajur ini untuk mengurangkan bilangan operasi I/O apabila "mengalih" data satu sel ke kiri. Tetapi keperluan untuk berulang melalui lajur untuk mencari yang perlu dipadam masih kekal, jadi => ​​O(n)
  • Sebaliknya, kini apabila mengemas kini data kita perlu mengemas kini lajur "kira" setiap kali, tetapi ini memerlukan masa yang berterusan, yang boleh diabaikan dalam rangka kerja simbol-O

Secara umum, pilihan 2 kelihatan lebih optimum sedikit, tetapi ia lebih seperti "evolusi dan bukannya revolusi." Untuk membuat "revolusi" kita perlukan Pilihan 3 (col).
Mari kita terbalikkan segala-galanya: kami akan melantik ID pengguna nama lajur! Apa yang akan ditulis dalam lajur itu sendiri tidak lagi penting bagi kami, biarlah nombor 1 (secara umum, perkara yang berguna boleh disimpan di sana, contohnya, kumpulan "keluarga / kawan / dll."). Pendekatan ini mungkin mengejutkan "orang awam" yang tidak bersedia yang tidak mempunyai pengalaman sebelumnya bekerja dengan pangkalan data NoSQL, tetapi pendekatan inilah yang membolehkan anda menggunakan potensi HBase dalam tugas ini dengan lebih berkesan:

RowKey
Lajur

Vasya
Petya: 1
Olya: 1
Dasha: 1

Peter
Masha: 1
Vasya: 1

Di sini kita mendapat beberapa kelebihan sekaligus. Untuk memahaminya, mari analisa struktur baharu dan anggarkan kerumitan pengiraan:

  • Membaca data: untuk menjawab soalan sama ada Vasya melanggan Olya, cukup untuk membaca satu lajur "Olya": jika ada, maka jawapannya adalah Benar, jika tidak - Salah => O(1)
  • Mengedit data: menambah rakan: Menambah rakan: cuma tambah lajur baharu “ID Rakan” => O(1)
  • Menukar data: memadam rakan: hanya keluarkan lajur ID Rakan => O(1)

Seperti yang anda lihat, kelebihan ketara model storan ini ialah dalam semua senario yang kami perlukan, kami beroperasi dengan hanya satu lajur, mengelak membaca keseluruhan baris daripada pangkalan data dan, lebih-lebih lagi, menyenaraikan semua lajur baris ini. Kita boleh berhenti di situ, tetapi...

Anda boleh berasa hairan dan pergi lebih jauh di sepanjang laluan mengoptimumkan prestasi dan mengurangkan operasi I/O apabila mengakses pangkalan data. Bagaimana jika kami menyimpan maklumat perhubungan yang lengkap terus dalam kekunci baris itu sendiri? Iaitu, jadikan komposit kunci seperti userID.friendID? Dalam kes ini, kita tidak perlu membaca lajur baris sama sekali (Pilihan 4(baris)):

RowKey
Lajur

Vasya.Petya
Petya: 1

Vasya.Olya
Olya: 1

Vasya.Dasha
Dasha: 1

Petya.Masha
Masha: 1

Petya.Vasya
Vasya: 1

Jelas sekali, penilaian semua senario manipulasi data dalam struktur sedemikian, seperti dalam versi sebelumnya, akan menjadi O(1). Perbezaan dengan pilihan 3 adalah semata-mata dalam kecekapan operasi I/O dalam pangkalan data.

Nah, "busur" terakhir. Adalah mudah untuk melihat bahawa dalam pilihan 4, kekunci baris akan mempunyai panjang berubah-ubah, yang mungkin menjejaskan prestasi (di sini kita ingat bahawa HBase menyimpan data sebagai satu set bait dan baris dalam jadual diisih mengikut kekunci). Selain itu, kami mempunyai pemisah yang mungkin perlu dikendalikan dalam beberapa senario. Untuk menghapuskan pengaruh ini, anda boleh menggunakan cincang daripada userID dan friendID, dan memandangkan kedua-dua cincang akan mempunyai panjang yang tetap, anda hanya boleh menggabungkannya, tanpa pemisah. Kemudian data dalam jadual akan kelihatan seperti ini (Pilihan 5(cincang)):

RowKey
Lajur

dc084ef00e94aef49be885f9b01f51c01918fa783851db0dc1f72f83d33a5994
Petya: 1

dc084ef00e94aef49be885f9b01f51c0f06b7714b5ba522c3cf51328b66fe28a
Olya: 1

dc084ef00e94aef49be885f9b01f51c00d2c2e5d69df6b238754f650d56c896a
Dasha: 1

1918fa783851db0dc1f72f83d33a59949ee3309645bd2c0775899fca14f311e1
Masha: 1

1918fa783851db0dc1f72f83d33a5994dc084ef00e94aef49be885f9b01f51c0
Vasya: 1

Jelas sekali, kerumitan algoritma untuk bekerja dengan struktur sedemikian dalam senario yang kami pertimbangkan akan sama dengan pilihan 4 - iaitu, O(1).
Secara keseluruhan, mari kita ringkaskan semua anggaran kerumitan pengiraan kami dalam satu jadual:

Menambah rakan
Memeriksa rakan
Mengeluarkan kawan

Pilihan 1 (lalai)
O (n)
O (n)
O (n)

Pilihan 2 (kiraan)
O (1)
O (n)
O (n)

Pilihan 3 (lajur)
O (1)
O (1)
O (1)

Pilihan 4 (baris)
O (1)
O (1)
O (1)

Pilihan 5 (cincang)
O (1)
O (1)
O (1)

Seperti yang anda lihat, pilihan 3-5 nampaknya adalah yang paling disukai dan secara teorinya memastikan pelaksanaan semua senario manipulasi data yang diperlukan dalam masa yang tetap. Dalam keadaan tugas kami, tidak ada keperluan yang jelas untuk mendapatkan senarai semua rakan pengguna, tetapi dalam aktiviti projek sebenar, adalah baik bagi kami, sebagai penganalisis yang baik, untuk "menjangka" bahawa tugas sedemikian mungkin timbul dan “hamparkan straw.” Oleh itu, simpati saya berada di sebelah pilihan 3. Tetapi kemungkinan besar bahawa dalam projek sebenar permintaan ini boleh diselesaikan dengan cara lain, oleh itu, tanpa wawasan umum tentang keseluruhan masalah, adalah lebih baik untuk tidak membuat kesimpulan akhir.

Penyediaan eksperimen

Saya ingin menguji hujah-hujah teori di atas secara praktikal - ini adalah matlamat idea yang timbul pada hujung minggu yang panjang. Untuk melakukan ini, adalah perlu untuk menilai kelajuan operasi "aplikasi bersyarat" kami dalam semua senario yang diterangkan untuk menggunakan pangkalan data, serta peningkatan pada masa ini dengan peningkatan saiz rangkaian sosial (n). Parameter sasaran yang menarik minat kami dan yang akan kami ukur semasa percubaan ialah masa yang dibelanjakan oleh "aplikasi bersyarat" untuk melaksanakan satu "operasi perniagaan". Dengan "urus niaga perniagaan" kami maksudkan salah satu daripada yang berikut:

  • Menambah seorang rakan baharu
  • Menyemak sama ada Pengguna A ialah rakan Pengguna B
  • Mengeluarkan seorang kawan

Oleh itu, dengan mengambil kira keperluan yang digariskan dalam pernyataan awal, senario pengesahan muncul seperti berikut:

  • Rakaman data. Menjana rangkaian awal bersaiz n secara rawak. Untuk lebih dekat dengan "dunia sebenar", bilangan rakan yang dimiliki oleh setiap pengguna juga merupakan pembolehubah rawak. Ukur masa "aplikasi bersyarat" kami menulis semua data yang dijana ke HBase. Kemudian bahagikan masa yang terhasil dengan jumlah bilangan rakan yang ditambah - ini adalah cara kita mendapatkan purata masa untuk satu "operasi perniagaan"
  • Membaca data. Bagi setiap pengguna, buat senarai "personaliti" yang anda perlukan untuk mendapatkan jawapan sama ada pengguna melanggan mereka atau tidak. Panjang senarai = kira-kira bilangan rakan pengguna, dan untuk separuh daripada rakan yang diperiksa jawapannya hendaklah "Ya", dan untuk separuh lagi - "Tidak". Semakan dilakukan dalam susunan sedemikian sehingga jawapan "Ya" dan "Tidak" silih berganti (iaitu, dalam setiap kes kedua kita perlu melalui semua lajur baris untuk pilihan 1 dan 2). Jumlah masa saringan kemudiannya dibahagikan dengan bilangan rakan yang diuji untuk mendapatkan purata masa saringan bagi setiap subjek.
  • Memadam data. Alih keluar semua rakan daripada pengguna. Selain itu, susunan pemadaman adalah rawak (iaitu, kami "mengocok" senarai asal yang digunakan untuk merekodkan data). Jumlah masa semakan kemudian dibahagikan dengan bilangan rakan yang dialih keluar untuk mendapatkan purata masa setiap cek.

Senario perlu dijalankan untuk setiap satu daripada 5 pilihan model data dan untuk saiz rangkaian sosial yang berbeza untuk melihat perubahan masa apabila ia berkembang. Dalam satu n, sambungan dalam rangkaian dan senarai pengguna untuk diperiksa mestilah, sudah tentu, sama untuk semua 5 pilihan.
Untuk pemahaman yang lebih baik, di bawah ialah contoh data yang dijana untuk n= 5. "Penjana" bertulis menghasilkan tiga kamus ID sebagai output:

  • yang pertama adalah untuk sisipan
  • yang kedua adalah untuk menyemak
  • ketiga – untuk pemadaman

{0: [1], 1: [4, 5, 3, 2, 1], 2: [1, 2], 3: [2, 4, 1, 5, 3], 4: [2, 1]} # всего 15 друзей

{0: [1, 10800], 1: [5, 10800, 2, 10801, 4, 10802], 2: [1, 10800], 3: [3, 10800, 1, 10801, 5, 10802], 4: [2, 10800]} # всего 18 проверяемых субъектов

{0: [1], 1: [1, 3, 2, 5, 4], 2: [1, 2], 3: [4, 1, 2, 3, 5], 4: [1, 2]} # всего 15 друзей

Seperti yang anda lihat, semua ID yang melebihi 10 dalam kamus untuk disemak adalah tepat yang pastinya akan memberikan jawapan Salah. Memasukkan, menyemak dan memadam "rakan" dilakukan dengan tepat mengikut urutan yang dinyatakan dalam kamus.

Percubaan telah dijalankan pada komputer riba yang menjalankan Windows 10, di mana HBase berjalan dalam satu bekas Docker, dan Python dengan Jupyter Notebook sedang berjalan di dalam bekas yang lain. Docker telah diperuntukkan 2 teras CPU dan 2 GB RAM. Semua logik, seperti emulasi "aplikasi bersyarat" dan "paip" untuk menjana data ujian dan mengukur masa, telah ditulis dalam Python. Perpustakaan digunakan untuk bekerja dengan HBase happybase, untuk mengira cincang (MD5) untuk pilihan 5 - hashlib

Dengan mengambil kira kuasa pengkomputeran komputer riba tertentu, pelancaran untuk n = 10, 30, … telah dipilih secara eksperimen. 170 – apabila jumlah masa operasi bagi kitaran ujian penuh (semua senario untuk semua pilihan untuk semua n) adalah lebih atau kurang munasabah dan sesuai semasa satu jamuan minum petang (secara purata 15 minit).

Di sini adalah perlu untuk membuat kenyataan bahawa dalam percubaan ini kami tidak menilai angka prestasi mutlak. Malah perbandingan relatif dua pilihan yang berbeza mungkin tidak betul sepenuhnya. Sekarang kami berminat dengan sifat perubahan masa bergantung pada n, kerana mengambil kira konfigurasi "pendirian ujian" di atas, sangat sukar untuk mendapatkan anggaran masa "dibersihkan" daripada pengaruh faktor rawak dan faktor lain ( dan tugas sedemikian tidak ditetapkan).

Hasil percubaan

Ujian pertama ialah bagaimana masa yang digunakan untuk mengisi senarai rakan berubah. Hasilnya adalah dalam graf di bawah.
Ciri-ciri mereka bentuk model data untuk NoSQL
Pilihan 3-5, seperti yang dijangkakan, menunjukkan masa "urus niaga perniagaan" yang hampir berterusan, yang tidak bergantung pada pertumbuhan saiz rangkaian dan perbezaan prestasi yang tidak dapat dibezakan.
Pilihan 2 juga menunjukkan prestasi malar, tetapi lebih teruk sedikit, hampir tepat 2 kali berbanding pilihan 3-5. Dan ini tidak boleh tidak bergembira, kerana ia berkait dengan teori - dalam versi ini bilangan operasi I/O ke/dari HBase adalah tepat 2 kali lebih besar. Ini boleh menjadi bukti tidak langsung bahawa bangku ujian kami, pada dasarnya, memberikan ketepatan yang baik.
Pilihan 1 juga, seperti yang dijangkakan, ternyata paling perlahan dan menunjukkan peningkatan linear dalam masa yang dihabiskan untuk menambah satu sama lain pada saiz rangkaian.
Sekarang mari kita lihat keputusan ujian kedua.
Ciri-ciri mereka bentuk model data untuk NoSQL
Pilihan 3-5 sekali lagi berkelakuan seperti yang diharapkan - masa yang tetap, bebas daripada saiz rangkaian. Pilihan 1 dan 2 menunjukkan peningkatan masa yang linear apabila saiz rangkaian meningkat dan prestasi yang serupa. Selain itu, pilihan 2 ternyata lebih perlahan - nampaknya disebabkan oleh keperluan untuk membaca pruf dan memproses lajur "kiraan" tambahan, yang menjadi lebih ketara apabila n berkembang. Tetapi saya masih akan mengelak daripada membuat sebarang kesimpulan, kerana ketepatan perbandingan ini agak rendah. Di samping itu, nisbah ini (pilihan mana, 1 atau 2, lebih cepat) berubah daripada larian ke larian (sambil mengekalkan sifat pergantungan dan "going neck and neck").

Nah, graf terakhir ialah hasil ujian penyingkiran.

Ciri-ciri mereka bentuk model data untuk NoSQL

Sekali lagi, tiada kejutan di sini. Pilihan 3-5 melakukan penyingkiran dalam masa yang tetap.
Lebih-lebih lagi, yang menarik, pilihan 4 dan 5, tidak seperti senario sebelumnya, menunjukkan prestasi yang ketara sedikit lebih buruk daripada pilihan 3. Nampaknya, operasi pemadaman baris lebih mahal daripada operasi pemadaman lajur, yang secara amnya logik.

Pilihan 1 dan 2, seperti yang dijangkakan, menunjukkan peningkatan masa yang linear. Pada masa yang sama, pilihan 2 secara konsisten lebih perlahan daripada pilihan 1 - disebabkan oleh operasi I/O tambahan untuk "mengekalkan" lajur kiraan.

Kesimpulan umum eksperimen:

  • Pilihan 3-5 menunjukkan kecekapan yang lebih tinggi kerana mereka mengambil kesempatan daripada HBase; Selain itu, prestasi mereka berbeza secara relatif antara satu sama lain dengan pemalar dan tidak bergantung pada saiz rangkaian.
  • Perbezaan antara pilihan 4 dan 5 tidak direkodkan. Tetapi ini tidak bermakna bahawa pilihan 5 tidak boleh digunakan. Berkemungkinan senario eksperimen yang digunakan, dengan mengambil kira ciri prestasi bangku ujian, tidak membenarkan ia dikesan.
  • Sifat peningkatan dalam masa yang diperlukan untuk melaksanakan "operasi perniagaan" dengan data secara amnya mengesahkan pengiraan teori yang diperoleh sebelum ini untuk semua pilihan.

Epilog

Eksperimen kasar yang dijalankan tidak boleh dianggap sebagai kebenaran mutlak. Terdapat banyak faktor yang tidak diambil kira dan memesongkan keputusan (turun naik ini terutamanya kelihatan dalam graf dengan saiz rangkaian yang kecil). Sebagai contoh, kelajuan penjimatan, yang digunakan oleh happybase, jumlah dan kaedah melaksanakan logik yang saya tulis dalam Python (saya tidak boleh mendakwa bahawa kod itu ditulis secara optimum dan berkesan menggunakan keupayaan semua komponen), mungkin ciri caching HBase, aktiviti latar belakang Windows 10 pada komputer riba saya, dsb. Secara umum, kita boleh menganggap bahawa semua pengiraan teori telah menunjukkan kesahihannya secara eksperimen. Nah, atau sekurang-kurangnya tidak mungkin untuk menyangkal mereka dengan "serangan langsung" sedemikian.

Kesimpulannya, cadangan untuk semua orang yang baru mula mereka bentuk model data dalam HBase: abstrak daripada pengalaman sebelumnya bekerja dengan pangkalan data hubungan dan ingat "perintah":

  • Apabila mereka bentuk, kami meneruskan dari tugas dan corak manipulasi data, dan bukan dari model domain
  • Akses cekap (tanpa imbasan jadual penuh) – hanya dengan kunci
  • Denormalisasi
  • Baris yang berbeza boleh mengandungi lajur yang berbeza
  • Komposisi dinamik pembesar suara

Sumber: www.habr.com

Tambah komen