Untuk mempartisi atau tidak?

8

Setelah membaca beberapa pertanyaan tentang SO, posting blog eksternal dan manual

Saya masih bertanya-tanya apakah saya harus pergi dengan partisi mempertimbangkan kasus saya atau tidak.

Kasus ini - disederhanakan

Menyimpan data pelanggan. Semua nama tabel yang disebutkan di bawah ini dibuat untuk kejelasan.

  1. Memiliki objek yang dapat diidentifikasi oleh pelanggan dan merupakan makhluk non-fisik, juga objek fisik di mana mereka sebenarnya disimpan jika perlu mengirim beberapa objek kembali ke pelanggan sesuai permintaan, atau memprosesnya dengan beberapa cara lain. Mereka dipetakan dalam hubungan banyak ke banyak. objects_nonphysical, objects_physical, objects_mapping_table.

  2. Hubungan many-to-many kedua adalah antara benda-benda non-fisik dan metrik mereka. Ada objek yang terikat dengan beberapa metrik. metrics,metrics_objects_nonphysical

  3. Objek non-fisik dan fisik memiliki tabel hierarki yang merupakan hubungan anak-orang tua. objects_nonphysical_hierarchy,objects_physical_hierarchy

Bergantung pada kebutuhan dan persyaratan masing-masing pelanggan, data tentang objek fisik dapat dipasok atau mungkin perlu dibuat dari awal. Pada dasarnya, yang perlu saya lakukan adalah:

  • Pertahankan sistem internal agar cepat INSERTdan SELECTpernyataan, karena di sinilah pemetaan akan berlangsung.

  • Menjaga sistem bagi pelanggan eksternal untuk melihat dan beroperasi pada objek non-fisik mereka - pengambilan data yang cepat. Sangat membutuhkan efisiensi untuk SELECTpernyataan - data ini tersedia bagi banyak pelanggan untuk dicari kapan pun mereka mau.

Pertimbangan saya

Mungkin ada pelanggan, yang dapat mengakses data, melihat dan mengoperasikannya, tetapi itu tidak perlu menjadi kontraktor tempat kami mendapatkan data dari / sedang memproses data.

Ini mendorong saya untuk memperkenalkan tabel partisi ke dalam sistem saya, mengingat saya selalu tahu data partisi mana yang harus dimasukkan ( partisi untuk kontraktor ), dan kemudian mempertahankan sistem untuk pelanggan eksternal di mana saya membutuhkan partisi untuk pelanggan (ini akan dilakukan dengan beberapa menunda menggunakan alat otomatisasi dan seperangkat aturan untuk menulis ulang data dengan cara pelanggan, sehingga untuk setiap pelanggan kami hanya akan memindai satu partisi untuk setiap tabel.

Volume data

Data saya akan terus tumbuh, terutama saat mengimpor objek dan metrik pelanggan baru. Kecepatan data baru yang masuk ke sistem tidak dapat diprediksi saat ini untuk jangka panjang. Sebenarnya tidak ada cara untuk mengukurnya tanpa mengetahui siapa yang akan menjadi pelanggan berikutnya. Saat ini hanya ada 2 pelanggan dengan lebih atau kurang 1M baris untuk setiap pelanggan di setiap tabel. Tetapi di masa depan saya memperkirakan pelanggan baru datang dengan volume 10 juta baris atau lebih juga.

Pertanyaan

Semua pertanyaan ini saling terkait satu sama lain.

  1. Haruskah pemartisian benar-benar dipertimbangkan di sini, atau apakah itu merupakan pembunuhan yang berlebihan? Saya menganggap itu berguna karena saya selalu memindai tepat satu partisi.
  2. Jika mempartisi adalah cara yang harus ditempuh, bagaimana cara menegakkan FKkendala yang paling efektif mempertimbangkan kebutuhan saya? Haruskah saya menggunakan constraint triggers, atau hanya menyimpannya di lapisan aplikasi untuk sistem internal, atau mungkin beberapa metode lain?
  3. Jika mempartisi bukan cara yang tepat, apa yang harus saya selami?

Jika tidak ada cukup data yang diberikan, beri tahu saya di komentar di bawah.

Kamil Gosciminski
sumber
3
Secara umum disarankan untuk memulai produksi tanpa overhead indeks, partisi dll. Maka jika perlu tambahkan indeks dan partisi dll.
alonk
1
Dengan mempartisi, Anda hanya akan mendapatkan percepatan pada jenis kueri tertentu saat menerima jenis kueri lainnya. Anda juga akan menerima menulis. Partisi seharusnya tidak menjadi hal pertama yang Anda raih, dan saya pikir Anda akan baik-baik saja menggunakan indeks polos untuk masa mendatang, dan menyeberangi jembatan itu ketika Anda sampai di sana. Baris 5M tidak terlalu besar. Ini mungkin blog yang bermanfaat dengan perbandingan cepat: if-not-true-then-false.com/2009/…
dizzystar
2
Saya setuju dengan dizzystar, saya tidak akan repot sekarang. Seberangi jembatan itu jika Anda mencapainya. Saat ini mempartisi di Postgres juga menyulitkan (jika bukan tidak mungkin) untuk menggunakan kunci asing yang tepat (ini mungkin berubah dengan 9,7 tetapi belum ada yang diselesaikan). Bahkan tabel dengan baris 50M belum tentu merupakan kandidat untuk dipartisi. Jika Anda terutama memiliki kondisi kesetaraan dalam pertanyaan Anda yang mengurangi jumlah baris secara substansial, pengindeksan yang baik dapat membuat Anda panjang jalan.
a_horse_with_no_name
1
Bagi saya tidak begitu jelas apa yang Anda maksud dengan 'partisi untuk kontraktor'. Apakah tabel yang digunakan kontraktor berbeda dengan yang dimiliki pelanggan? Apakah pernah terjadi bahwa pelanggan A harus mengakses data dari pelanggan B? Jika tidak, maka memisahkan data spesifik pelanggan ke dalam skema per pelanggan mungkin merupakan cara yang harus ditempuh - tetapi tidak harus untuk kinerja, tetapi untuk pemisahan masalah (peningkatan keamanan / privasi dan sebagainya).
dezso

Jawaban:

1

Ada banyak ujung terbuka dalam pertanyaan Anda, tetapi pemartisian oleh pelanggan bisa menjadi cara untuk pergi - terutama jika:

  • Anda mengharapkan banyak pelanggan,
  • masing-masing dari mereka dapat memiliki banyak data ("ton" berarti lebih dari ukuran cache RAM),
  • sebagian besar dataset mereka akan saling eksklusif (setiap pelanggan melihat subset data yang berbeda).

ATURAN atau pemicu adalah overhead kinerja, dan dapat dihindari.

Pertimbangkan sesuatu seperti ini:

BEGIN;

CREATE USER tenant1;
CREATE USER tenant2;

CREATE SCHEMA app;
CREATE SCHEMA tenant1;
CREATE SCHEMA tenant2;

CREATE TABLE app.objects_nonphysical(id int);
CREATE TABLE app.objects_physical(id int);
CREATE TABLE app.objects_mapping(id int);    
CREATE TABLE tenant1.objects_nonphysical() INHERITS(app.objects_nonphysical);
CREATE TABLE tenant1.objects_physical() INHERITS(app.objects_physical);
CREATE TABLE tenant1.objects_mapping() INHERITS(app.objects_mapping);
CREATE TABLE tenant2.objects_nonphysical() INHERITS(app.objects_nonphysical);
CREATE TABLE tenant2.objects_physical() INHERITS(app.objects_physical);
CREATE TABLE tenant2.objects_mapping() INHERITS(app.objects_mapping);

GRANT USAGE ON SCHEMA tenant1 TO tenant1;
GRANT USAGE ON SCHEMA tenant2 TO tenant2;
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA tenant1 TO tenant1;
GRANT SELECT,INSERT,UPDATE,DELETE ON ALL TABLES IN SCHEMA tenant2 TO tenant2;

/* TEST: simulate login as customer */
SET SESSION AUTHORIZATION tenant2;
/* No schema needed - default search_path works */
SELECT count(*) FROM objects_nonphysical; 

ROLLBACK;

Anda tidak perlu pemicu / aturan apa pun untuk mempertahankannya.

Ada ujung terbuka di sini - itu hanya konsep ... Beberapa masalah:

  • PK, FK, dan indeks tidak "diwariskan".
  • bahkan jika Anda membuatnya, PK tidak diberlakukan di tabel master
  • Anda dapat mengatasinya dengan menggunakan urutan yang sama untuk semua penyewa
  • jelas, aplikasi harus disesuaikan untuk model ini
filiprem
sumber
0

Tidak ada ruginya jika Anda menerapkan partisi sekarang, tetapi gunakan satu partisi sampai sistem Anda benar-benar membutuhkan yang baru. Dari segi kinerja, hanya akan ada overhead kecil, untuk menangani kunci primer dan semacamnya.

Saya sarankan menggunakan aturan untuk mengarahkan ulang sisipan, dan tabel eksternal untuk kunci primer (mis. CREATE TABLE objects_physical_ids (id bigserial NOT NULL PRIMARY KEY), Bersama dengan satu pemicu fungsi yang menyisipkan baris dalam tabel id dan menyalinnya ke NEW.id (mis. INSERT INTO objects_physical_ids DEFAULT VALUES RETURNING id INTO NEW.id;), Dan pemicu lain yang berhubungan dengan penghapusan dan pembaruan, dan pemicu yang menjalankan pemicu fungsi tersebut untuk setiap tabel yang diwarisi (jangan lupa untuk melakukan ini ketika Anda membuat tabel yang diwarisi!). Kemudian semua tabel terkait dapat memiliki FOREIGN KEYke tabel id yang relevan (termasuk tindakan kunci asing seperti ON UPDATEatau ON DELETE).

Ziggy Crueltyfree Zeitgeister
sumber
2
Aturan dan pemicu pasti memiliki overhead, dan mudah untuk diukur. Selain itu, mereka menambah kompleksitas dan membuat debugging (jauh) lebih sulit. Juga, setelah turun dengan cara ini beberapa kali, saya sarankan (tanpa harus mengakui semua detail) untuk menyimpan tabel induk kosong dan satu atau lebih partisi anak. Saat mengubah skema partisi, ini mungkin berguna.
dezso