Gantek

PostgreSQL’de TOAST 1

 

PostgreSQL’de TOAST (The Oversized-Attribute Storage Technique) Kavramı

 

Diğer veritabanlarında olduğu gibi, PostgreSQL kayıtları depolamak için sabit büyüklükte sayfalar kullanır. PostgreSQL’de sayfa büyüklüğü 8KB’tır. Veritabanı dosyalarına 8 KB’lık paketler halinde yazarken, bu sayfaları 8KB’lık önbellek blokları halinde bellekte tutar. Sayfalar ne kadar çok kaydı içinde barındırırsa o kadar disk I/O işlemleri azalır ve dolayısıyla veritabanının performansı artar.

 

Bir veritabanı sayfasının (8KB) başında “Header” yani başlık yapısı bulunur. Hemen ardından, sayfadaki kayıt sayısı kadar ItemID adı verilen bölüm bulunur. ItemID, sayfa içinde kaydın başladığı yeri baştan itibaren bayt olarak yeri ve uzunluğunu içeren bir veri tipidir. Kayıtlar da sayfanın sonunda itibaren başına doğru genişleyen yapıdadır. Bu şekilde sayfa alanının daha efektif şekilde kullanılması gerçekleştirilir.

 

 

Eğer bir kayıt içinde nvarchar veya JSON gibi ucu açık ve tam olarak ne kadar yer kaplayacağı bilinmeyen veri tiplerini varsa ne olacak? Elbette ki bu kolonlar 8KB’ın içine sığmayacaktır. Bu kolonları sıkıştırsak ne olur? Peki 8 KB’ın içine sığmayanlar ne olacak?

 

PostgreSQL tasarım itibariyle, bir sayfada minimum 4 kaydın bulunabileceği varsayımına göre tasarlanmıştır. Bu da her kaydın yaklaşık 2KB’lık bir alanı kaplaması demektir. Peki 2KB’ı geçerse ne olacak? PostgreSQL, kayıt 2KB’ı geçerse buna sebep olan kolonlardaki alanlardaki değerleri sıkıştırarak kaydı 2KB içine sığmasına zorlar. Bir kayıttaki kolon/alan değeri sıkıştırılsa dahi 2KB’ın aşağısına inmiyorsa o zaman sayfadan çıkarılmalı ve ayrı bir yerde depolanmalıdır.

 

PostgreSQL, nvarchar, JSON, vb türde ucu açık kolonu bulunan tablolar yaratıldığında, otomatik olarak her bir kolon için pg_toast adı verilen bir dizi tablo türetir. 2KB’a sığmayan kayıtlarda sıkıştırılmasına rağmen sığmayan bu alanlar TOAST tablolarında (pg_toast.*) tutulur.

 

 

PostgreSQL v7.1’den önce, bir tabloda yer alan bir kaydın en fazla 8KB olmasına izin veriliyordu. Bu şekilde bir sayfa içinde minimum 1 kayıt bulunabiliyordu. Bu durum PostgreSQL için önemli bir kısıttı. PostgreSQL v7.1’le (13.04.2001) birlikte TOAST (The Oversized-Attribute Storage Technique) adı verilen yöntemle, 2KB’dan büyük kayıtların “out-of-line” şekilde, tablo dosyalarından farklı dosyalarda bulunan pg_toast tablolarına kaydedilmesi sağlanmıştır. Kayıtlar içinde kaydın 2KB’dan büyük olabilmesine sebep olan büyük veri alanları (örneğin nvarchar veya JSON) doğrudan sayfaya kaydedilmez ve ayrı bir tablo olan TOAST tablolarına kaydedilir.

 

TOAST yöntemi, büyük veri alanlarını iki farklı yöntemle depolar:

  • Büyük veri alanını sayfa içinde tutabilmek için, sıkıştırır ve sayfaya sığdırabildiği zaman, sıkıştırılmış veriyi kaydın bulunduğu sayfaya koyar.
  • Sıkıştırma sonucunda büyük veri alanı 2KB’ın altına inmediyse, o zaman “out-of-line” depolama yöntemi uygulanır. Büyük veri alanını, «postgres» servis veritabanı içinde yer alan özel bir tablodaki (*) bölümlere yazar. Bu tablodaki sayfalar, «toast» adı verilen parçalara (1996 Bayt + 18 Bayt pointer) bölünmüştür.

 

TOAST sayesinde, PostgreSQL JSON dokümanlarının efektif şekilde depolanmasını sağlamış ve daha sonraki dönemde NoSQL veritabanlarında olduğu gibi JSON dokümanları depolamak için kullanılmaya başlanmıştır.

 

2001’de yapılan bu inovasyon, JSON veri tipinin 2016’da SQL standardı içine alınmasıyla birlikte, PostgreSQL’in en fazla JSON depolanan veritabanı olmasını sağlamıştır.

 

TOAST yöntemi sıkıştırma yöntemini gerektirmemekle birlikte yerden kazanmak için ilk zamanlarda pglz adı verilen sıkıştırma algoritması, TOAST tablolarında kullanılmıştır. Daha sonraki dönemde v14 ile birlikte lz4 yöntemi de kullanılmaya başlanmıştır. lz4 sıkıştırma algoritması pglz’ye göre çok daha hızlı bir sıkıştırma çözümü sunmaktadır.

 

Sıkıştırma sadece değişken uzunlukta olan veri tipleri için geçerlidir ve kolonun depolama modu «main» veya «extended» olduğunda kullanılır. PostgreSQL’de satır veya sayfa sıkıştırması bulunmaz. Değişken uzunlukta veriler arasında 2KB’dan uzun olanları sıkıştırabilir. Sıkıştırma algoritmaları, genellikle 1K ve 1MB arasında büyüklükteki veriler için optimum sıkıştırma oranı sağlamaktadır.

 

pglz ve lz4 algoritmaları kıyaslandığında, pglz’nin daha yavaş ve CPU yoğun bir işlem olduğunu ama iyi bir sıkıştırma sağladığı görülmektedir. lz4 ise son derece hızlıdır ama sıkıştırma oranı daha küçüktür.

 

Linkler

 

https://www.postgresql.org/docs/current/storage-toast.html

https://www.timescale.com/blog/what-is-toast-and-why-it-isnt-enough-for-data-compression-in-postgres/

https://www.percona.com/blog/unlocking-the-secrets-of-toast-how-to-optimize-large-column-storage-in-postgresql-for-top-performance-and-scalability/

https://www.enterprisedb.com/postgres-tutorials/postgresql-toast-and-working-blobsclobs-explained