Apache Phoenix performansı için en iyi yöntemler

Apache Phoenix performansının en önemli yönü, temel alınan Apache HBase'i iyileştirmektir. Phoenix, HBase'in üzerinde SQL sorgularını taramalar gibi HBase işlemlerine dönüştüren bir ilişkisel veri modeli oluşturur. Tablo şemanızın tasarımı, birincil anahtarınızdaki alanların seçilmesi ve sıralanması ve dizin kullanımınız Phoenix performansını etkiler.

Tablo şeması tasarımı

Phoenix'te tablo oluşturduğunuzda, bu tablo bir HBase tablosunda depolanır. HBase tablosu, birlikte erişilen sütun gruplarını (sütun aileleri) içerir. Phoenix tablosundaki bir satır, HBase tablosundaki bir satırdır ve her satır bir veya daha fazla sütunla ilişkili sürümlenmiş hücrelerden oluşur. Mantıksal olarak, tek bir HBase satırı, her biri aynı satır anahtarı değerine sahip olan anahtar-değer çiftlerinden oluşan bir koleksiyondur. Diğer bir ifadeyle, her anahtar-değer çiftinin bir satır anahtarı özniteliği vardır ve bu satır anahtarı özniteliğinin değeri belirli bir satır için aynıdır.

Phoenix tablosunun şema tasarımı birincil anahtar tasarımını, sütun ailesi tasarımını, tek sütun tasarımını ve verilerin nasıl bölümlendiğini içerir.

Birincil anahtar tasarımı

Phoenix'teki bir tabloda tanımlanan birincil anahtar, verilerin temel alınan HBase tablosunun satır anahtarı içinde nasıl depolandığını belirler. HBase'de, belirli bir satıra erişmenin tek yolu satır anahtarıdır. Ayrıca, HBase tablosunda depolanan veriler satır anahtarına göre sıralanır. Phoenix, satırdaki sütunların her birinin değerlerini birincil anahtarda tanımlanma sırasıyla birleştirerek satır anahtarı değerini oluşturur.

Örneğin, kişiler tablosunun adı, soyadı, telefon numarası ve adresi aynı sütun ailesindedir. Artan bir sıra numarasına göre birincil anahtar tanımlayabilirsiniz:

satır anahtarı adres telefon firstName lastName
1000 1111 San Gabriel Dr. 1-425-000-0002 John Dole
8396 5415 San Gabriel Dr. 1-230-555-0191 Calvin Raji

Bununla birlikte, lastName ile sık sık sorgu yapıyorsanız, her sorgu her lastName değerini okumak için tam tablo taraması gerektirdiğinden bu birincil anahtar iyi çalışmayabilir. Bunun yerine lastName, firstName ve sosyal güvenlik numarası sütunlarında birincil anahtar tanımlayabilirsiniz. Bu son sütun, aynı adreste baba ve oğul gibi aynı ada sahip iki sakini birbirinden ayırabilmektir.

satır anahtarı adres telefon firstName lastName socialSecurityNum
1000 1111 San Gabriel Dr. 1-425-000-0002 John Dole 111
8396 5415 San Gabriel Dr. 1-230-555-0191 Calvin Raji 222

Bu yeni birincil anahtarla Phoenix tarafından oluşturulan satır anahtarları şöyle olacaktır:

satır anahtarı adres telefon firstName lastName socialSecurityNum
Dole-John-111 1111 San Gabriel Dr. 1-425-000-0002 John Dole 111
Raji-Calvin-222 5415 San Gabriel Dr. 1-230-555-0191 Calvin Raji 222

Verilen tablonun ilk satırında, satır anahtarına ilişkin veriler gösterildiği gibi gösterilir:

satır anahtarı anahtar değer
Dole-John-111 adres 1111 San Gabriel Dr.
Dole-John-111 telefon 1-425-000-0002
Dole-John-111 firstName John
Dole-John-111 lastName Dole
Dole-John-111 socialSecurityNum 111

Bu satır anahtarı artık verilerin yinelenen bir kopyasını depolar. Bu değer temel alınan HBase tablosundaki her hücreye dahil edildiğinden, birincil anahtarınıza eklediğiniz sütunların boyutunu ve sayısını göz önünde bulundurun.

Ayrıca, birincil anahtarın monoton olarak artan değerleri varsa, yazma etkin noktaları oluşturmamaya yardımcı olmak için tabloyu tuz demetleriyle oluşturmanız gerekir. Bkz . Verileri bölümleme.

Sütun ailesi tasarımı

Bazı sütunlara diğerlerinden daha sık erişiliyorsa, sık erişilen sütunları nadiren erişilen sütunlardan ayırmak için birden çok sütun ailesi oluşturmanız gerekir.

Ayrıca, belirli sütunlara birlikte erişilme eğilimi varsa, bu sütunları aynı sütun ailesine yerleştirin.

Sütun tasarımı

  • Büyük sütunların G/Ç maliyetleri nedeniyle VARCHAR sütunlarını yaklaşık 1 MB'ın altında tutun. Sorguları işlerken HBase, hücreleri istemciye göndermeden önce tam olarak gerçekleştirir ve istemci bunları uygulama koduna teslim etmeden önce tam olarak alır.
  • Sütun değerlerini protobuf, Avro, msgpack veya BSON gibi sıkıştırılmış bir biçim kullanarak depolayın. Daha büyük olduğundan JSON önerilmez.
  • Gecikme süresini ve G/Ç maliyetlerini kesmek için depolamadan önce verileri sıkıştırmayı göz önünde bulundurun.

Verileri bölümleme

Phoenix, verilerinizin dağıtıldığı bölgelerin sayısını denetlemenize olanak tanır ve bu da okuma/yazma performansını önemli ölçüde artırabilir. Phoenix tablosu oluştururken verilerinizi tuzlayabilir veya önceden bölebilirsiniz.

Oluşturma sırasında tabloya tuz eklemek için tuz demetlerinin sayısını belirtin:

CREATE TABLE CONTACTS (...) SALT_BUCKETS = 16

Bu tuzlama, değerleri otomatik olarak seçerek tabloyu birincil anahtarların değerlerine böler.

Tablo bölmelerinin nerede olduğunu denetlemek için, bölme işleminin gerçekleştiği aralık değerlerini sağlayarak tabloyu önceden bölebilirsiniz. Örneğin, üç bölgeye bölünmüş bir tablo oluşturmak için:

CREATE TABLE CONTACTS (...) SPLIT ON ('CS','EU','NA')

Dizin tasarımı

Phoenix dizini, dizine alınan tablodaki verilerin bir kısmını veya tümünü depolayan bir HBase tablosudur. Dizin, belirli sorgu türleri için performansı artırır.

Birden çok dizini tanımlayıp bir tabloyu sorguladığınızda, Phoenix otomatik olarak sorgu için en iyi dizini seçer. Birincil dizin, seçtiğiniz birincil anahtarlara göre otomatik olarak oluşturulur.

Beklenen sorgular için, sütunlarını belirterek ikincil dizinler de oluşturabilirsiniz.

Dizinlerinizi tasarlarken:

  • Yalnızca ihtiyacınız olan dizinleri oluşturun.
  • Sık güncelleştirilen tablolardaki dizin sayısını sınırlayın. Bir tabloya Güncelleştirmeler hem ana tabloya hem de dizin tablolarına yazma işlemlerine dönüşür.

İkincil dizinler oluşturma

İkincil dizinler, depolama alanı ve yazma hızı karşılığında tam tablo taraması olabilecek verileri nokta aramasına dönüştürerek okuma performansını geliştirebilir. tablo oluşturulduktan sonra ikincil dizinler eklenebilir veya kaldırılabilir ve mevcut sorgularda değişiklik yapılması gerekmez; sorgular daha hızlı çalışır. Gereksinimlerinize bağlı olarak, kapsanan dizinler, işlevsel dizinler veya her ikisini de oluşturmayı göz önünde bulundurun.

Kapsanan dizinleri kullanma

Kapsanan dizinler, dizine alınan değerlere ek olarak satırdaki verileri de içeren dizinlerdir. İstenen dizin girdisini bulduktan sonra birincil tabloya erişmeye gerek yoktur.

Örneğin, örnek kişi tablosunda yalnızca socialSecurityNum sütununda ikincil bir dizin oluşturabilirsiniz. Bu ikincil dizin socialSecurityNum değerlerine göre filtreleyen sorguları hızlandırır, ancak diğer alan değerlerini almak için ana tabloda başka bir okuma gerekir.

satır anahtarı adres telefon firstName lastName socialSecurityNum
Dole-John-111 1111 San Gabriel Dr. 1-425-000-0002 John Dole 111
Raji-Calvin-222 5415 San Gabriel Dr. 1-230-555-0191 Calvin Raji 222

Ancak, normalde socialSecurityNum değeri verilen firstName ve lastName değerlerini aramak isterseniz, dizin tablosunda gerçek veriler olarak firstName ve lastName değerlerini içeren kapsanan bir dizin oluşturabilirsiniz:

CREATE INDEX ssn_idx ON CONTACTS (socialSecurityNum) INCLUDE(firstName, lastName);

Bu kapsanan dizin, aşağıdaki sorgunun yalnızca ikincil dizini içeren tablodan okuyarak tüm verileri almasını sağlar:

SELECT socialSecurityNum, firstName, lastName FROM CONTACTS WHERE socialSecurityNum > 100;

İşlevsel dizinleri kullanma

İşlevsel dizinler, sorgularda kullanılmasını beklediğiniz rastgele bir ifadede dizin oluşturmanıza olanak sağlar. İşlevsel bir dizininiz olduğunda ve sorgu bu ifadeyi kullandığında, veri tablosu yerine sonuçları almak için dizin kullanılabilir.

Örneğin, bir kişinin birleşik adı ve soyadı üzerinde büyük/küçük harfe duyarsız aramalar yapmanıza olanak sağlayan bir dizin oluşturabilirsiniz:

CREATE INDEX FULLNAME_UPPER_IDX ON "Contacts" (UPPER("firstName"||' '||"lastName"));

Sorgu tasarımı

Sorgu tasarımında dikkat edilmesi gereken başlıca noktalar şunlardır:

  • Sorgu planını anlayın ve beklenen davranışını doğrulayın.
  • Verimli bir şekilde katılın.

Sorgu planını anlama

SQLLine'da, Phoenix'in gerçekleştirdiği işlemlerin planını görüntülemek için EXPLAIN ve ardından SQL sorgunuzu kullanın. Planın şu şekilde olup olmadığını denetleyin:

  • Uygun olduğunda birincil anahtarınızı kullanır.
  • Veri tablosu yerine uygun ikincil dizinleri kullanır.
  • MÜMKÜN olduğunda TABLO TARAMA yerine ARALIK TARAMA veya TARAMAYI ATLA işlevini kullanır.

Plan örnekleri

Örneğin, uçuş gecikmesi bilgilerini depolayan FLIGHT adlı bir tablonuz olduğunu varsayalım.

ile tüm uçuşları airlineid19805seçmek için, burada airlineid birincil anahtarda veya herhangi bir dizinde olmayan bir alan vardır:

select * from "FLIGHTS" where airlineid = '19805';

Açıklanan komutu aşağıdaki gibi çalıştırın:

explain select * from "FLIGHTS" where airlineid = '19805';

Sorgu planı şöyle görünür:

CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN FULL SCAN OVER FLIGHTS
   SERVER FILTER BY AIRLINEID = '19805'

Bu planda, UÇUŞLARDA TAM TARAMA ifadesini not edin. Bu tümcecik, yürütmenin daha verimli ARALıK TARAMASı veya TARAMAYı ATLA seçeneğini kullanmak yerine tablodaki tüm satırlar üzerinde TABLO TARAMAsı yaptığını gösterir.

Şimdi 2 Ocak 2014'te uçuş toplamını 1'den büyük olan taşıyıcıya AA yönelik uçuşları sorgulamak istediğinizi varsayalım. Örnek tabloda year, month, dayofmonth, carrier ve flightnum sütunlarının bulunduğunu ve bunların tümünün bileşik birincil anahtarın parçası olduğunu varsayalım. Sorgu aşağıdaki gibi görünür:

select * from "FLIGHTS" where year = 2014 and month = 1 and dayofmonth = 2 and carrier = 'AA' and flightnum > 1;

Şimdi şu sorgunun planını inceleyelim:

explain select * from "FLIGHTS" where year = 2014 and month = 1 and dayofmonth = 2 and carrier = 'AA' and flightnum > 1;

Sonuçta elde edilen plan:

CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER FLIGHTS [2014,1,2,'AA',2] - [2014,1,2,'AA',*]

Köşeli ayraç içindeki değerler, birincil anahtarların değer aralığıdır. Bu durumda, aralık değerleri 2014 yılı, 1. ay ve dayofmonth 2 ile sabitlenir, ancak 2 ile başlayan ve () ile* başlayan flightnum değerlerine izin verir. Bu sorgu planı, birincil anahtarın beklendiği gibi kullanıldığını onaylar.

Ardından, FLIGHTS tablosunda yalnızca taşıyıcı alanında bulunan adlı carrier2_idx bir dizin oluşturun. Bu dizin ayrıca , tailnum, originve flightnum verilerinin de dizinde depolandığı kapsanan sütunları içerirflightdate.

CREATE INDEX carrier2_idx ON FLIGHTS (carrier) INCLUDE(FLIGHTDATE,TAILNUM,ORIGIN,FLIGHTNUM);

Aşağıdaki sorguda olduğu gibi taşıyıcıyı flightdate ve tailnumile birlikte almak istediğinizi varsayalım:

explain select carrier,flightdate,tailnum from "FLIGHTS" where carrier = 'AA';

Bu dizinin kullanıldığını görmeniz gerekir:

CLIENT 1-CHUNK PARALLEL 1-WAY ROUND ROBIN RANGE SCAN OVER CARRIER2_IDX ['AA']

Açıklama planı sonuçlarında gösterilebilen öğelerin tam listesi için Apache Phoenix Ayarlama Kılavuzu'ndaki Planları Açıklama bölümüne bakın.

Verimli bir şekilde katılın

Genellikle, özellikle sık yapılan sorgularda bir taraf küçük olmadığı sürece birleştirmelerden kaçınmak istersiniz.

Gerekirse, ipucuyla /*+ USE_SORT_MERGE_JOIN */ büyük birleşimler yapabilirsiniz, ancak büyük birleştirme çok sayıda satıra göre pahalı bir işlemdir. Sağ taraftaki tüm tabloların genel boyutu kullanılabilir belleği aşarsa ipucunu /*+ NO_STAR_JOIN */ kullanın.

Senaryolar

Aşağıdaki yönergelerde bazı yaygın desenler açıklanmaktadır.

Yoğun okunan iş yükleri

Yoğun okuma kullanım örnekleri için dizinleri kullandığınızdan emin olun. Ayrıca, okuma zamanı ek yükü kazanmak için kapsanan dizinler oluşturmayı göz önünde bulundurun.

Yoğun yazma iş yükleri

Birincil anahtarın monoton olarak arttığı yoğun yazma iş yükleri için, gereken ek taramalar nedeniyle genel okuma aktarım hızına bağlı olarak yazma etkin noktalarını önlemeye yardımcı olmak için tuz demetleri oluşturun. Ayrıca, çok sayıda kayıt yazmak için UPSERT kullanırken autoCommit özelliğini kapatın ve kayıtları toplu işleyin.

Toplu silmeler

Büyük bir veri kümesini silerken, delete sorgusunu vermeden önce autoCommit'i açın; böylece istemcinin silinen tüm satırların satır anahtarlarını hatırlaması gerekmez. AutoCommit, istemcinin DELETE'den etkilenen satırları arabelleğe almalarını önler, böylece Phoenix bunları istemciye döndürmek zorunda kalmadan doğrudan bölge sunucularında silebilir.

Sabit ve Yalnızca Ekle

Senaryonuz veri bütünlüğüne göre yazma hızını destekliyorsa tablolarınızı oluştururken önceden yazma günlüğünü devre dışı bırakmayı göz önünde bulundurun:

CREATE TABLE CONTACTS (...) DISABLE_WAL=true;

Bu ve diğer seçeneklerle ilgili ayrıntılar için bkz . Apache Phoenix Dilbilgisi.

Sonraki adımlar