8 Haziran 2019 Cumartesi

TOAST ( The Oversized-Attribute Storage Technique)


 TOAST, bir büyük boyutlu veri saklama tekniğidir. PostgreSQL 7.1 ile gelmiş olup, büyük verileri sıkıştırarak ve/veya bölerek depolamayı amaçlar. 
PostgreSQL veri düzenlemesi bir satırın (row), birden fazla sayfa (page) ile depolanmasına olanak sunmaz. Bu sayfalar sabit büyüklüğe sahiptir ve genel olarak 8kB olarak ayarlanmıştır. 
TOAST tekniği ile belli büyüklüğün üzerindeki satırlar ( TOAST_TUPLE_TRESHOLD değeri -ön tanımlı olarak 2Kb-) sıkıştırılır ve gerektiği taktirde farklı yığınlara (chunk) ayrılarak “TOAST tablosu” adındaki tablolarda saklanır. Sıkıştırılma ve ayrılma işlemi TOAST_TUPLE_TARGET ile belirtilen büyüklüğün altına getirilene kadar devam eder. Ön tanımlı olarak bu değer de 2kB’dır, ayarlanabilir. 

Bunu değiştirmek için

> ALTER TABLE <tablo_ismi> SET (toast_tuple_target = n)  #128 <= n <= 8160

sorgusu kullanılabilir.


TOAST'u tam olarak anlayabilmek için öncelikle bazı kavramlara hakim olmamız gerekir. 

  • Bir verinin TOAST ile depolanabilmesi için “varlena” yani “variable length array” gösteriliminin olması gerekmektedir. Bu veri tipi PostgreSQL’in basit yapılı ama bir o kadar da karmaşık bir özelliğidir. Basit olarak açıklamak gerekirse, verinin ilk dört baytı, asıl verinin uzunluğunu belirtir. TOAST tekniği için bu veri tipinin önemi, bir veriyi TOASTlanmış halinden geri çevirirken (deTOAST) veri büyüklüğünün bilinmesinin gerekmesidir.
  • Bununla birlikte TOAST tekniği, varlena yapısının ilk baytının yüksek mertebeden iki bitini (high-order bits), verinin saklanma biçimini belirtmek için kullanır. 
  • PostgreSQL, LZ(Lempel-Ziv) sıkıştırma tekniklerinin uyarlanmış bir halini kullanır. Basitçe açıklandığında: tekrar eden veri kalıpları, dinamik bir sözlük kullanılarak kısaltılır. Bu şekilde sıkıştırılmış veriler etiketler yardımı ile (tags) anlamlı hale getirilir. Bu etiketler kullanılarak sıkıştırılan veri, hızlı bir şekilde eski haline getirilebilir. Sıkıştırma algoritması ile ilgili daha detaylı bilgi edinmek için src/common/pg_lzcompress.c kaynak kodu içerisindeki yorum satırlarını okumak yeterli olacaktır. 
  • TOAST işlemi dış depolama (out-of-line storage) veya iç depolama (in-line storage) olarak ayarlanabilir. Out-of-line depolamada “TOAST pointer datum” verinin sıkıştırılma durumunu, diskteki veya bellekteki yerini ve TOAST tablosunun ID’sini belirlemek için kullanılır. 


TOAST Depolama Teknikleri


Diskte Saklanan TOAST tabloları (On-disk)


TOAST uygulanabilecek satırlara sahip tabloların, belli bir OID’ye sahip bir de TOAST tablosu bulunur. TOAST’lanmış veriler bu tablolarda ayrı yığınlar halinde tutulurlar(chunk), ayrılan yığınların büyüklükleri MAX_CHUNK_SIZE ile ayarlanabilir. Ön tanımlı olarak bu değer bir tablonun bir sayfaya(page) sığmasını sağlayacak biçimde ayarlanmıştır. 

Her bir yığın TOAST tablosunda farklı bir satırı oluşturur. Üç sütundan oluşan bu tabloların değişkenleri şu şekildedir: 

chunk_id: OID olarak ayarlanmış, TOAST’lanmış veriye özel bir ID.

chunk_seq: Satırdaki yığının sıra numarasıdır. Her bir yığının veriyi oluşturmada bir yeri vardır. Her yığının bir ID’si ve sıra numarası olması değerin özgün haline hızlı ve bozulma olmadan dönmesini sağlar. 

chunk_data: Sıkıştırılmış ve/veya ayrılmış verinin asıl yığınıdır. 

Bir TOAST tablosunun ID’si pg_class katalog tablosunun reltoastrelid kolonunda saklanır. 
İstenilen taktirde, bir tablonun ilgili TOAST tablosunun ID’sini aşağıdaki sorgu ile öğrenmek mümkündür:

> SELECT reltoastrelid::regclass FROM pg_class WHERE relname = “tablo_ismi”;

Alınan çıktıda TOAST tablosunun ismi olacaktır. 

Bir TOAST tablosunu, herhangi bir tabloyu görüntülüyormuş gibi görüntüleyebiliriz:

> SELECT * FROM pg_toast.pg_toast_0000 ;

Chunk_data” yani verinin kendisi, sıkıştırılmış ve ayrılmış olduğundan anlamlı bir yapıda olmayacaktır.


TOAST stratejileri diskte saklanacak TOAST tabloları için kullanıcı tarafından ayarlanabilir. Bu şekilde saklanan verinin büyüklüğüne, istenilen depolama yerine (in-line, out-of-line) ve uygun sıkıştırılma şekline göre daha etkili TOAST stratejisi kullanılabilir. 

Plain: Sıkıştırma veya dış-depolama(out-of-line) işlemlerinden birini engeller. Eğer tablodaki veri şekilleri TOAST işlemine uygun değilse sadece bu strateji ile TOAST işlemi gerçekleştirilebilir.  

Extended: Hem sıkıştırma hem out-of-line depolamaya izin verir. TOAST işleminin ön tanımlı stratejisi budur. Sırayla büyüklüğü azaltmak için önce sıkıştırma, yeterli gelmezse dış-depolama işlemine başvurmaya ayarlanmıştır. 

External: Out-of-line depolamaya izin verirken sıkıştırmayı engeller. Bu şekilde saklanan yığınlara ayrılmış veriler hala anlamlı olacağından, bu stratejinin alt dizi (substring) kullanacak, text veya bytea değişkenleri içeren işlemlerde kullanılması hız açısından etkili olacaktır. 

Main: Sıkıştırmaya izin verdiği halde out-of-line depolamaya sıkıştırma işleminin sonuna kadar izin vermez. Veri sıkıştırılabildiği kadar sıkıştırıldıktan sonra hala bir satıra sığdırılamıyorsa, son çare olarak out-of-line depolama yapılır. (PostgreSQL’in kullandığı “pg_lzcompress” sıkıştırma algoritması, toplamda %96’ya ulaşabilecek kadar bir sıkıştırma oranına sahiptir.)

Bir tablonun kullandığı depolama tekniğini 

> \d+ <tablo_ismi>  

komutu ile, "Storage" sütununun altında görüntüleyebilirsiniz. 

Bu tekniği değiştirmek için ise aşağıdaki komut kullanılır:

> ALTER TABLE <tablo_ismi> ALTER COLUMN <sütun_ismi> SET STORAGE <istenilen_starteji>;


Bellekte Saklanan TOAST Tabloları (in-memory)


TOAST pointer, diskte olmayıp, sadece güncel işlemde (server process) bellekte bulunan bir veriyi gösterebilir. Bu şekilde saklanan tablolar uzun ömürlü değillerdir. 

Bu pointerlar kendi içinde ikiye ayrılır: “pointers to indirect data” ve “pointers to expanded data

Indirect TOAST pointers” yani dolaylı olarak veriyi gösteren pointerlar basitçe bellekte bulunan bir veriyi gösterir. Çoğu zaman “logical decoding” sırasında 1GB’dan büyük fiziksel satırlar yaratmamak için kullanılır. Veri kaybı olasılığı olduğundan kullanım olanakları geniş değildir. 

Expanded TOAST pointers” yani karmaşık verileri gösteren pointerlar, diskte saklanması verimli olmayan veri tipleri için kullanılır. 


Hiçbir bellekte saklanan TOAST pointer diske yazılmaz. Güncel “server process” ötesinde saklanmak istendiği taktirde, önce TOAST’lanmamış in-line haline döndürülür, ardından gerekirse diskte saklanılması için on-disk TOAST ile diske yazılır. 


KISITLAMALAR 


TOAST uygulanacak tablonun boyutu


 Out-of-line yani dış-depolama ile saklanan verilerin oluşturduğu tabloların da belli bir veri saklama olacağı vardır. Bir TOAST tablosunda aynı OID’den iki tane olmaması için 2^32 yani tablo başına en fazla 4 bilyon değer dış-depolama ile saklanabilir. Teoride doğru olsa da, pratikte bu büyüklüğe ulaşabilecek tabloları bölerek saklamak çok daha verimli olacaktır. TOAST tablosu büyüdükçe sorgu zamanları ve tutarları(cost) artacaktır. 


TOAST uygulanacak tablonun sütun sayısı


Dış-depolama tekniği ile tutulan tablolarda veriler ayrı bir yerde tutulsa da pointerlar tablo da tutulacağından satır boyutu sıfıra inmez. Bir pointer yaklaşık olarak 18 bayttır bu da bir tablonun sütun sayısını yaklaşık olarak 450 olarak ayarlamamıza izin verir.




KAYNAK