Sütun türünü CHAR'dan (36) UUID'ye değiştirmek için zaman ayırmalı mıyım?


14

Veritabanımda zaten birkaç milyon satır var. Şemamı tasarlarken PostgreSQL UUID veri türünü bilmiyordum.

Tablolardan birinde, günde yaklaşık 500 bin kayıtla büyüyen 16 milyon satır (parça başına yaklaşık 3,5 milyon ila 4 milyon kayıt) bulunur. Gerektiğinde hala üretim sistemini birkaç saatliğine indirme lüksüne sahibim. Bir ya da iki hafta içinde bu lüksüm olmayacak.

Benim sorum şu, buna değecek mi? JOIN performansını merak ediyorum, disk alanı kullanımı (tam gzip'd dökümü 1.25 GiB), o tür şeyler.

Tablo şeması:

# \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.)

Yanıtlar:


13

UUID türüne geçmeyi düşünürdüm. char(36)40 bayt uuidalır, 16 alır, böylece satır başına 24 bayt tasarruf edersiniz, bu da sizin için günde 12 MB, bir yıl sonra 4 GB'a eşit olacaktır. Artı dizinler. Hangi donanıma sahip olduğunuza bağlı olarak, çok fazla değil, ama olabilir. Ve bunun gibi daha fazla geliştirme fırsatınız varsa eklenir.

Ayrıca, şemanızda bunun interaction_iddoğru biçimde olmasını sağlayan hiçbir kısıtlama görmüyorum . Doğru türü kullanmak size bunu verecektir.

Ancak bunu isterseniz, kullanmaktan bigintdaha fazla tasarruf edersiniz ve daha iyi performans elde edersiniz . Uygulamanızın bigintbir ID sütununun çalışmayacağı kadar büyük olması pek olası değildir.


Dağıtılmış bir sistemim var: birden fazla veri kaynağı etkileşimler için kimlikler oluşturur, bu yüzden düğüm kimliği için N biti ayırmadıkça düz bir BIGINT kullanamam.
François Beausoleil

3
@ FrançoisBeausoleil, düğüm kimliği için N bit ayırmak, her Nth numarasını bir dizide kullanmaya eşittir (ve bu nedenle uygulanması kolaydır). Ayrıca, bileşik anahtarlar kullanmayı da düşünebilirsiniz.
Unreason

1
Birden fazla dizinin (düğüm kimliğiyle) koordine edilmesi, pratikte ve insan hatasına eğilimli bir idari güçlüktür. Bu senaryoda UUID'leri kullanmamak için hiçbir neden göremiyorum, özellikle de bitler günümüzde ucuz olduğundan (hem bellek hem de depolama). Aslında, bu senaryo UUID'lerin onlarca yıl önce icat edilmesinin sebebidir: Merkezi koordinasyon olmadan verileri dağıtılmış sistemler arasında paylaşmak .
Basil Bourque

6

Hayal gücünün herhangi bir uzantısı ile bir postgres kişi değilim, ama SQL Server'dan bildiklerime dayanarak, bir veri sayfasına sığabilecek daha fazla satır, sahip olacağınız daha iyi performans (diskten veri okumak genellikle en pahalı işlem). Bu nedenle, 36 ish 1 bayt genişlik alanından 16 bayt GUID'ye geçmek doğrudan bir maliyet tasarrufu gibi görünüyor. Ne kadar az okuma yaparsanız, sonuçları o kadar hızlı döndürebilirsiniz. Tüm bunlar elbette bir GUID / UUID'nin tablonun iş ihtiyaçlarını karşıladığını varsayar. Bir UUID bunu tatmin ederse, bir bigint olur mu? Bu, depolama alanınızın satır başına 8 bayt daha fazla tıraş olmasını sağlar.

Düzenle 1

İçin karakter verisi Postgres, onlar için ek bir depolama maliyeti yoktur. 127 baytın altındaki kısa dizeler 1 baytlık bir ek yüke sahipken, daha uzun bir şey 4 bayt içerir, bu da ikinci yanıt verenin 36 baytlık bir alan için 40 baytlık bir maliyetle ortaya çıktığını gösterir. Ancak dize sıkıştırması için de bir seçenek var, bu yüzden belki de tam 40'a mal olmayacak. Nihai maliyetin ne olacağını söyleyemem ama temeller kalır: 16 baytın üzerindeki herhangi bir şey depolama maliyetini artıracak, okunması daha uzun sürecek ve daha fazla bellek tüketir.

Kısa bir dize (126 bayta kadar) için depolama gereksinimi, 1 bayt artı karakter durumunda boşluk dolgusu içeren gerçek dizedir. Daha uzun dizelerin 1 yerine 4 bayt ek yükü vardır. Uzun dizeler sistem tarafından otomatik olarak sıkıştırılır, bu nedenle diskteki fiziksel gereksinim daha az olabilir.


3

Alan sorununun yanı sıra, doğru veri türünü kullanmak için her tabloyu değiştirmeniz gerektiğini veya katılma performansınızın kötü bir şekilde depolanacağını unutmayın.


Bu belli bir şeydi, ama hatırlattığın için teşekkürler.
François Beausoleil

3
Böyle büyük değişiklikler yaparken, her şeyi yazmanın (hatırlamak ne kadar basit olursa olsun) genellikle işe yaradığını görüyorum.
mrdenny

3

G / Ç tasarrufuna dönüşen veri ve indekslerin boyutundaki (başkaları tarafından söylendiği gibi) kaydetmeye ek olarak, dikkate almanız gereken şey, nasıl yeni değerler üreteceğiniz interaction_idve dizinler ve sorgu koşulları (birleşimler).

Dizin için daha küçük olacaktır, ancak sorgularınızın birçoğu UUID'lere geçmek için dizin taramaları kullanıyorsa, dizin taramalarını imkansız hale getirebilir (UUID'leri nasıl oluşturacağınıza bağlı olarak) ve bigintçok daha iyi bir seçim olabilir.

Son olarak, gerçek performans etkisi kullanım alışkanlıklarınıza ve veri dağıtımınıza da bağlı olduğundan, testleri çalıştırmalı ve değişikliklerinizi test edebileceğiniz bir geliştirme ve test ortamına sahip olmalısınız.

Bu, performans üzerindeki etkisi hakkında çok daha kesin bir cevap verecektir.


Yararlı katkı için teşekkürler ve siteye hoş geldiniz :)
Jack diyor topanswers.xyz

Erişim kalıplarım tarih aralıkları, ekran_adı kullanılarak JOINing veya UUID. Benzersiz kimlik üzerinde aralık taraması beklenmemektedir. Cevabınız için teşekkürler, çok bilgilendirici.
François Beausoleil
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.