Haruskah saya menginvestasikan waktu untuk mengubah jenis kolom dari CHAR (36) ke UUID?


14

Saya sudah memiliki beberapa juta baris di basis data saya. Saya tidak tahu tentang tipe data PostgreSQL UUID ketika saya merancang skema saya.

Salah satu tabel memiliki 16 juta baris (sekitar 3,5 juta hingga 4 juta catatan per pecahan), tumbuh sekitar 500 ribu rekor per hari. Saya masih memiliki kemewahan untuk menurunkan sistem produksi selama beberapa jam jika diperlukan. Saya tidak akan memiliki kemewahan ini dalam satu atau dua minggu.

Pertanyaan saya adalah, apakah akan bermanfaat untuk melakukannya? Saya bertanya-tanya tentang kinerja BERGABUNG, penggunaan ruang disk (dump gzip'd penuh adalah 1,25 GiB), hal-hal semacam itu.

Skema tabel adalah:

# \d twitter_interactions
                Table "public.twitter_interactions"
         Column          |            Type             | Modifiers 
-------------------------+-----------------------------+-----------
 interaction_id          | character(36)               | not null
 status_text             | character varying(1024)     | not null
 screen_name             | character varying(40)       | not null
 twitter_user_id         | bigint                      | 
 replying_to_screen_name | character varying(40)       | 
 source                  | character varying(240)      | not null
 tweet_id                | bigint                      | not null
 created_at              | timestamp without time zone | not null
Indexes:
    "twitter_interactions_pkey" PRIMARY KEY, btree (interaction_id)
    "twitter_interactions_tweet_id_key" UNIQUE, btree (tweet_id)
    "index_twitter_interactions_on_created_at" btree (created_at)
    "index_twitter_interactions_on_screen_name" btree (screen_name)
Triggers:
    insert_twitter_interactions_trigger BEFORE INSERT ON twitter_interactions FOR EACH ROW EXECUTE PROCEDURE twitter_interactions_insert_trigger()
Number of child tables: 9 (Use \d+ to list them.)

Jawaban:


13

Saya akan mempertimbangkan untuk mengubah ke jenis UUID. char(36)membutuhkan 40 byte, uuid16, jadi Anda akan menghemat 24 byte per baris, yang untuk Anda akan sama dengan 12 MB sehari, 4 GB setelah satu tahun. Ditambah indeks. Tergantung pada perangkat keras apa yang Anda miliki, itu tidak banyak, tetapi bisa jadi. Dan itu bertambah jika Anda memiliki lebih banyak peluang peningkatan seperti ini.

Juga, saya tidak melihat kendala dalam skema Anda yang memastikan bahwa interaction_idsebenarnya dalam format yang tepat. Menggunakan tipe yang tepat akan memberi Anda itu juga.

Jika Anda suka ini, bagaimanapun, menggunakan bigintakan menghemat lebih banyak dan memiliki kinerja yang lebih baik. Sangat tidak mungkin aplikasi Anda begitu besar sehingga bigintkolom untuk ID tidak akan berfungsi.


Saya memiliki sistem terdistribusi: beberapa sumber data menghasilkan ID untuk interaksi, jadi saya tidak dapat menggunakan BIGINT polos kecuali saya memesan N bit untuk ID node.
François Beausoleil

3
@ FrançoisBeausoleil, pemesanan bit N untuk ID node sama dengan menggunakan setiap nomor N dalam urutan (dan karena itu mudah diimplementasikan). Anda juga dapat mempertimbangkan menggunakan kunci komposit.
masuk akal

1
Mengkoordinasikan banyak sekuens (dengan ID simpul) merupakan kerumitan administratif dalam praktik dan rawan kesalahan manusia. Saya tidak melihat alasan untuk tidak menggunakan UUID dalam skenario ini, terutama karena bit yang murah saat ini (baik memori dan penyimpanan). Memang, skenario ini adalah alasan utama UUID diciptakan beberapa dekade yang lalu: Untuk berbagi data di antara sistem terdistribusi tanpa koordinasi terpusat .
Basil Bourque

6

Saya bukan orang postgres dengan imajinasi apa pun, tetapi berdasarkan apa yang saya ketahui dari SQL Server, semakin banyak baris yang dapat Anda masukkan ke halaman data, semakin baik kinerja yang akan Anda miliki (membaca data dari disk biasanya operasi paling mahal). Dengan demikian, akan dari 36 ish 1 byte lapangan luas untuk 16 byte GUID tampaknya penghematan biaya lurus ke depan. Semakin sedikit bacaan yang dapat Anda keluarkan, semakin cepat Anda dapat mengembalikan hasilnya. Semua ini tentu saja mengasumsikan bahwa GUID / UUID memenuhi kebutuhan bisnis tabel. Jika memenuhi UUID itu, akan sebuah bigint ? Itu lebih jauh mencukur biaya penyimpanan Anda 8 byte per baris.

Edit 1

Untuk data karakter di Postgres, ada biaya penyimpanan tambahan untuk mereka. String pendek, di bawah 127 byte memiliki overhead 1 byte sementara yang lebih lama memiliki 4 byte, yaitu bagaimana responden kedua menghasilkan biaya 40 byte untuk bidang 36 byte. Tetapi ada juga opsi untuk kompresi string jadi mungkin tidak akan dikenakan biaya 40 penuh. Saya tidak tahu berapa biaya finalnya tetapi fundamental tetap: apa pun lebih dari 16 byte akan meningkatkan biaya penyimpanan, butuh waktu lebih lama untuk membaca dari dan mengkonsumsi lebih banyak memori.

Persyaratan penyimpanan untuk string pendek (hingga 126 byte) adalah 1 byte plus string yang sebenarnya, yang mencakup ruang bantalan dalam kasus karakter. String yang lebih panjang memiliki 4 byte overhead daripada 1. String yang panjang dikompresi oleh sistem secara otomatis, sehingga persyaratan fisik pada disk mungkin kurang.


3

Selain masalah ruang, perlu diingat bahwa Anda harus mengubah setiap tabel untuk menggunakan tipe data yang benar atau kinerja gabungan Anda akan menurun.


Itu diberikan, tetapi terima kasih telah mengingatkan saya.
François Beausoleil

3
Ketika melakukan perubahan besar seperti ini, saya menemukan bahwa menuliskan semuanya (tidak peduli betapa sederhananya hal itu untuk diingat) biasanya terbayar.
mrdenny

3

Selain penghematan dalam ukuran data dan indeks (seperti yang dikatakan oleh orang lain), yang tidak berarti penghematan I / O, hal yang perlu Anda pertimbangkan adalah bagaimana Anda akan menghasilkan nilai baru untuk interaction_id dan apa dampaknya pada indeks dan kondisi permintaan (bergabung).

Untuk indeks - ini akan lebih kecil, namun jika banyak pertanyaan Anda menggunakan pemindaian indeks, beralih ke UUID mungkin membuat pemindaian indeks menjadi tidak mungkin (tergantung pada bagaimana Anda akan menghasilkan UUID) dan bigint mungkin merupakan pilihan yang jauh lebih baik.

Akhirnya, karena dampak kinerja aktual tergantung juga pada pola penggunaan dan distribusi data Anda, Anda harus menjalankan tes dan memiliki lingkungan pengembangan dan pengujian di mana Anda dapat menguji perubahan Anda.

Ini akan memberi Anda jawaban yang jauh lebih tepat tentang dampak pada kinerja.


Terima kasih atas kontribusi yang bermanfaat dan selamat datang di situs ini :)
Jack mengatakan coba topanswers.xyz

Pola akses saya adalah melalui rentang tanggal, BERGABUNG menggunakan screen_name, atau oleh UUID. Tidak ada pemindaian rentang pada ID unik yang diantisipasi. Terima kasih atas jawaban Anda, sangat informatif.
François Beausoleil
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.