Bir SELECT ifadesine MAPJOIN ipucu ekleyerek birleştirmenin (join) karıştırma (shuffle) ve azaltma (reduce) aşamalarını atlayıp doğrudan eşleme (map) aşamasında yürütülmesini sağlayabilirsiniz. Bu yaklaşım, büyük bir tabloyu bir veya daha fazla küçük tablo ile birleştirirken veri aktarım yükünü azaltır ve sorgu performansını artırır. İyimserleştirici (optimizer), sorgunuz için otomatik olarak eşleme aşaması birleştirmesini uygulamadığında MAPJOIN kullanın.
Nasıl çalışır
MaxCompute'da standart bir JOIN işlemi üç aşamadan geçer: eşleme (map), karıştırma (shuffle) ve azaltma (reduce). Gerçek birleştirme mantığı, düğümler arasında veri karıştırmayı gerektiren azaltma aşamasında yürütülür.
MAPJOIN bu süreci değiştirir: Belirtilen küçük tablonun tüm içeriğini eşleme aşamasında belleğe yükler. Her bir eşleyici (mapper), bellekteki verilere karşı yerel olarak birleştirme işlemini yapar; böylece karıştırma ve azaltma aşamaları tamamen ortadan kalkar.
İpucu, belleğe yüklenecek küçük tabloyu belirtir. Büyük tablodan satır okuyan her eşleyici için küçük tablo bellekten tamamen okunur:
SELECT /*+ mapjoin(a) */ a.shop_name, a.total_price, b.total_price
FROM sale_detail_sj a JOIN sale_detail b
ON a.total_price < b.total_price OR a.total_price + b.total_price < 500;
Bu örnekte, a (sale_detail_sj tablosunun takma adı) küçük tablodur. İpucu a değerini belirttiğinden, her eşleyicide belleğe yüklenen nesne a olur.
Sınırlamalar
Bellek ve tablo sayısı
| Kısıtlama | Sınır | Notlar |
|---|---|---|
| Tüm küçük tablolar için toplam bellek | 512 MB | MaxCompute'da depolanan sıkıştırılmış boyut değil, veriler belleğe yüklendikten ve sıkıştırması açıldıktan sonraki ölçüm dikkate alınır |
| Maksimum küçük tablo sayısı | 128 | 128'den fazla tablo belirtilirse sözdizimi hatası döndürülür |
Desteklenen JOIN türleri
| JOIN türü | Destekleniyor mu? | Gereksinim |
|---|---|---|
| INNER JOIN | Evet | Sol veya sağ tablo büyük tablo olabilir |
| LEFT OUTER JOIN | Evet | Sol tablo büyük tablo olmalıdır |
| RIGHT OUTER JOIN | Evet | Sağ tablo büyük tablo olmalıdır |
| FULL OUTER JOIN | Hayır | — |
Kullanım notları
/*+ mapjoin(<table_name>) */ ifadesini SELECT anahtar kelimesinden hemen sonra ekleyin. Aşağıdaki hususları göz önünde bulundurun:
Orijinal tablo adlarını değil, takma adları referans alın. Küçük tablonun veya alt sorgunun bir takma adı varsa, ipucu içinde bu takma adı kullanın.
Alt sorgular küçük tablo olarak desteklenir. Tablo referansı yerine bir alt sorgu kullanabilir ve ipucunda bunun takma adına başvurabilirsiniz.
Birden çok küçük tabloyu virgülle ayırın:
/*+ mapjoin(a,b,c) */Eşitlik dışı birleştirmeler ve OR koşulları desteklenir. Standart MaxCompute SQL, ON koşulunda eşitlik dışı birleştirmelere veya OR mantığına izin vermez ancak MAPJOIN buna olanak tanır.
Kartezyen çarpımlar desteklenir; bunun için
ON 1 = 1kullanılır (örneğin,SELECT /*+ mapjoin(a) */ a.id FROM shop a JOIN table_name b ON 1=1). Ancak bu durum çıktı veri hacmini önemli ölçüde artırabilir.
SCALAR, IN, NOT IN, EXISTS ve NOT EXISTS gibi alt sorgu türleri, yürütme sırasında JOIN işlemlerine dönüştürülebilir. Alt sorgu sonucu küçük bir tablo niteliği taşıyorsa, eşleme aşaması birleştirme algoritmasını açıkça uygulamak üzere alt sorgu ifadesine bir MAPJOIN ipucu ekleyin.
Örnek veriler
Bu konudaki örnekler sale_detail ve sale_detail_sj tablolarını kullanır. Tabloları oluşturmak ve örnek verileri eklemek için aşağıdaki ifadeleri çalıştırın.
-- Create a partitioned table named sale_detail.
CREATE TABLE IF NOT EXISTS sale_detail
(
shop_name STRING,
customer_id STRING,
total_price DOUBLE
)
PARTITIONED BY (sale_date STRING, region STRING);
CREATE TABLE IF NOT EXISTS sale_detail_sj
(
shop_name STRING,
customer_id STRING,
total_price DOUBLE
)
PARTITIONED BY (sale_date STRING, region STRING);
-- Add partitions.
ALTER TABLE sale_detail ADD PARTITION (sale_date='2013', region='china');
ALTER TABLE sale_detail_sj ADD PARTITION (sale_date='2013', region='china');
-- Insert sample data.
INSERT INTO sale_detail PARTITION (sale_date='2013', region='china')
VALUES ('s1','c1',100.1),('s2','c2',100.2),('s3','c3',100.3);
INSERT INTO sale_detail_sj PARTITION (sale_date='2013', region='china')
VALUES ('s1','c1',100.1),('s2','c2',100.2),('s5','c2',100.2),('s2','c2',100.2);
Örnek
sale_detail_sj (küçük tablo, takma adı a) ile sale_detail (büyük tablo, takma adı b) tablolarını eşitlik dışı bir koşul kullanarak birleştirin. a tablosundaki total_price değeri b tablosundaki total_price değerinden küçükse VEYA her iki fiyatın toplamı 500'den küçükse ilgili satırları döndürün.
-- Allow a full scan on the partitioned table.
SET odps.sql.allow.fullscan=true;
-- Use MAPJOIN with a non-equi join condition.
SELECT /*+ mapjoin(a) */
a.shop_name,
a.total_price,
b.total_price
FROM sale_detail_sj a JOIN sale_detail b
ON a.total_price < b.total_price OR a.total_price + b.total_price < 500;
Sorgu aşağıdaki sonucu döndürür:
+-----------+-------------+--------------+
| shop_name | total_price | total_price2 |
+-----------+-------------+--------------+
| s1 | 100.1 | 100.1 |
| s2 | 100.2 | 100.1 |
| s5 | 100.2 | 100.1 |
| s2 | 100.2 | 100.1 |
| s1 | 100.1 | 100.2 |
| s2 | 100.2 | 100.2 |
| s5 | 100.2 | 100.2 |
| s2 | 100.2 | 100.2 |
| s1 | 100.1 | 100.3 |
| s2 | 100.2 | 100.3 |
| s5 | 100.2 | 100.3 |
| s2 | 100.2 | 100.3 |
+-----------+-------------+--------------+