Betik modu, birden fazla SQL ifadesini tek bir birim olarak derleyip gönderir. Bu işlem, kuyruğa bir kez alınan ve tek bir işte çalışan tek bir yürütme planı oluşturur. Bu yaklaşım; birden fazla koordineli ifade gerektiren ETL veri işlem hatları, periyodik toplu işleme ve sorgu orkestrasyonu senaryoları için idealdir. Normal mod (atomik yürütme, varsayılan) ve adım adım yürütme modu (seri yürütme) desteği sunar.
Betik modu maliyet tahmini desteklemez. Gerçek ücretler faturalama ayrıntılarınıza göre belirlenir.
Tek bir betik en fazla 10.000 tabloya başvurabilir. Her başvuru ayrı ayrı sayılır; aynı tabloya yapılan tekrarlı başvurular ve görünüm tanımlarındaki tablolar da buna dahildir.
Birden fazla veri kaynağı için veri hazırlama işlemleri önemli ölçüde farklı zamanlarda tamamlanıyorsa (örneğin biri saat 01:00'de, diğeri saat 07:00'de), bunları tek bir Betik Modu SQL işinde birleştirmek için tablo değişkeni kullanmayın.
Kullanım Senaryoları
Karmaşık ifadeleri yeniden yazma: Derin iç içe geçmiş alt sorguları, okunabilir tablo değişkeni atamalarından oluşan bir diziye ayırın.
Çoklu ifadeli işlem hatları oluşturma: Mantıksal olarak ilişkili ifadeleri tek bir işte birleştirerek kuyruk ve zamanlama ek yükünü azaltın. Normal modda tüm ifadeler atomik olarak yürütülür. Adım adım yürütme modunda ifadeler seri halde çalışır; bu durum, yazdıktan sonra okuma senaryoları veya diğer platformlardan geçişler için uygundur. Daha fazla bilgi için bkz. Yürütme Modları.
Sözdizimi
İfade türleri: Betik modu SET ifadelerini, bazı DDL ifadelerini ve DML ifadelerini destekler. DESC ve SHOW gibi sonuç görüntüleyen ifadeler desteklenmez.
İfade sırası: Bir betik sabit bir
SET→DDL→DMLsırasını izlemelidir. Her bölüm sıfır veya daha fazla ifade içerebilir, ancak farklı bölümlerden gelen ifadeleri iç içe yerleştiremezsiniz.
-- 1. SET
SET odps.sql.type.system.odps2=true;
[SET odps.stage.reducer.num=xxx;]
[SET odps.sql.step.script.mode=true;] -- Enable step-by-step execution mode
[...]
-- 2. DDL
CREATE TABLE table1 xxx;
[CREATE TEMPORARY TABLE table2 xxx;] -- Create a temporary table
[...]
-- 3. DML&DQL
@var1 := SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table3
[WHERE where_condition];
@var2 := SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table4
[WHERE where_condition];
@var3 := SELECT [ALL | DISTINCT] var1.select_expr, var2.select_expr, ...
FROM @var1 JOIN @var2 ON ...;
INSERT OVERWRITE|INTO TABLE [PARTITION (partcol1=val1, partcol2=val2 ...)]
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM @var3;
[@var4 := SELECT [ALL | DISTINCT] var1.select_expr, var1.select_expr, ... FROM @var1
UNION ALL | UNION
SELECT [ALL | DISTINCT] var2.select_expr, var2.select_expr, ... FROM @var2;
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
AS
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM @var4;]
[...]
Yürütme Modları
Betik modu iki yürütme modunu destekler.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DDL Sözdizimi
Geçici tablo oluşturma
Geçici tablolar, aynı betik içinde yeniden kullanılmak üzere ara sonuçları önbelleğe alır. Yazdıktan sonra okuma düzenine dayandıkları için yalnızca adım adım yürütme modunda desteklenirler.
Sözdizimi
CREATE TEMPORARY TABLE <table_name> (
<col_name> <data_type>, ...
)
[LIFECYCLE <days>]
[AS <select_statement>];
Parametreler
|
|
|
|
|
|
|
|
|
|
|
|
Sınırlamalar
Geçici tablolar adım adım yürütme modu gerektirir. Betiğinizin SET bölümüne
SET odps.sql.step.script.mode=true;ekleyin.Geçici tabloya yalnızca oluşturulduğu betik içinde erişilebilir.
Geçici tablolar bölümlenmiş tablolar veya işlemsel tablolar olamaz.
Geçici bir tabloyu açıkça silmek için
DROP TABLEifadesi betikteki son ifade olmalıdır.Tek bir betikte 20'den fazla geçici tablo oluşturmaktan kaçının.
Standart tablo oluşturma
Betik modu standart tabloların oluşturulmasını destekler. Sözdizimi ayrıntıları için bkz. CREATE TABLE.
DML ve DQL Sözdizimi
İfade Sınırlamaları
Sonuç görüntüleyen ifadeler: Bir betik, bağımsız bir
SELECTifadesi gibi ekran çıktısı üreten yalnızca bir ifade içerebilir. Birden fazla ifade bulunması hataya neden olur. Betiklerde bu tür ifadeleri kullanmaktan kaçının.CREATE TABLE AS: Bu ifadeyi betik başına yalnızca bir kez kullanabilirsiniz ve son yürütülebilir ifade olmalıdır. Önce tabloyu oluşturup ardından veri eklemenizi öneririz.
Karışık yazma modları: Aynı betik içinde aynı tablo için hem OVERWRITE hem de INTO kullanamazsınız. İşlemsel tablolar ve standart tablolar üzerindeki DML işlemleri karıştırılamaz.
Yazdıktan sonra okuma: Normal modda, aynı betik içinde bir tabloya yazıp ardından ondan okumak hataya neden olur. Bu sorunu çözmek için ya bir tablo değişkeni kullanın ya da adım adım yürütme moduna geçin. Adım adım yürütme modu yazdıktan sonra okuma işlemini destekler ancak işlemsel tablolar veya bölümlenmiş tablolar için geçerli değildir. Ayrıntılı örnek için bkz. Örnek 3: Normal modda yazdıktan sonra okuma.
Değişkenler
Sözdizimi
-- Declare a variable by using @. Supported types include TABLE and any MaxCompute data type.
@var1 <type>
-- Assign a value by using :=
@var1 := <select_statement>
Kullanım Notları
-
Tablo türündeki bir değişkeni belirli bir veri türüne sahip bir değişkene atayamazsınız. Örneğin, aşağıdaki sözdizimine izin verilmez:
@a TABLE (name STRING); @a := SELECT 'tom'; @b STRING; @b := SELECT * FROM @a; -
Değişkenler sabit değerleri depolayabilir.
SELECT * FROM @varkullanarak bir değişkenin değerini skaler değere dönüştürebilirsiniz. Aşağıdaki örnekte gösterildiği gibi bir sabit, tek satırlık bir tabloda da depolanabilir. Dönüşüm sözdizimi hakkında daha fazla bilgi için bkz. alt sorgu.@a := SELECT 10; -- Assign the constant 10 @b := SELECT key, value + (SELECT * FROM @a) FROM t2; -- Use @a as a scalar SELECT * FROM @b;
IF İfadeleri
Koşullara dayalı olarak yürütme akışını kontrol etmek için IF ifadelerini kullanın.
Sözdizimi
-- Single branch
IF (condition) BEGIN
statements
END
-- Multi-branch
IF (condition) BEGIN
statements
END ELSE IF (condition2) BEGIN
statements
END ELSE BEGIN
statements
END
Kullanım Notları
Bir dal yalnızca tek bir ifade içeriyorsa,
BEGINveENDanahtar sözcükleri isteğe bağlıdır (Java'daki{ }benzeri).CREATE TABLE,ALTER TABLEveTRUNCATE TABLEgibi DDL ifadeleri bir IF dalı içinde desteklenmez.-
Koşul iki türü destekler:
Boolean ifadesi: Dal derleme zamanında belirlenir.
Boolean skaler alt sorgusu: Dal çalışma zamanında belirlenir. MaxCompute birden fazla iş gönderebilir.
Örnek 1: IF ifadesinde koşul BOOLEAN türünde bir ifadedir. Bu tür IF ELSE ifadesi, aşağıdaki örnekte gösterildiği gibi hangi dalın yürütüleceğini derleme zamanında belirleyebilir:
@date := '20190101';
@row TABLE(id STRING);
IF (CAST(@date AS BIGINT) % 2 == 0) BEGIN
@row := SELECT id FROM src1;
END ELSE BEGIN
@row := SELECT id FROM src2;
END
INSERT OVERWRITE TABLE dest SELECT * FROM @row;
Örnek 2: IF ifadesindeki koşul bir Boolean skaler alt sorgusudur. Bu tür IF ELSE ifadesi için yürütme dalı çalışma zamanında belirlenir; bu durum MaxCompute'in birden fazla iş göndermesini gerektirir:
@i BIGINT;
@t TABLE(id BIGINT, value BIGINT);
IF ((SELECT COUNT(*) FROM src WHERE a = '5') > 1) BEGIN
@i := 1;
@t := SELECT @i, @i*2;
END ELSE BEGIN
@i := 2;
@t := SELECT @i, @i*2;
END
SELECT id, value FROM @t;
Örnekler
Örnek 1: Temel Örnek
Aşağıdaki betik, üç kaynak tablodan gelen verileri birleştirir ve union işlemine tabi tutar, ardından sonuçları iki hedef tabloya ekler. Tüm ifadeler tek bir DAG'de derlenir ve atomik olarak yürütülür.
CREATE TABLE IF NOT EXISTS dest(key STRING, value BIGINT) PARTITIONED BY (d STRING);
CREATE TABLE IF NOT EXISTS dest2(key STRING, value BIGINT) PARTITIONED BY (d STRING);
@a := SELECT * FROM src WHERE value > 0;
@b := SELECT * FROM src2 WHERE key IS NOT NULL;
@c := SELECT * FROM src3 WHERE value IS NOT NULL;
@d := SELECT a.key, b.value FROM @a LEFT OUTER JOIN @b ON a.key = b.key AND b.value > 0;
@e := SELECT a.key, c.value FROM @a INNER JOIN @c ON a.key = c.key;
@f := SELECT * FROM @d UNION SELECT * FROM @e UNION SELECT * FROM @a;
INSERT OVERWRITE TABLE dest PARTITION (d='20171111') SELECT * FROM @f;
@g := SELECT e.key, c.value FROM @e JOIN @c ON e.key = c.key;
INSERT OVERWRITE TABLE dest2 PARTITION (d='20171111') SELECT * FROM @g;
Örnek 2: Adım adım modda yazdıktan sonra okuma
Aşağıdaki betik, aynı betik içinde yazdıktan sonra okuma işlemi gerçekleştirmek üzere adım adım yürütme modunu etkinleştirir.
SET odps.sql.step.script.mode=true;
DROP TABLE IF EXISTS foo_t1;
DROP TABLE IF EXISTS foo_t2;
CREATE TABLE foo_t1(a STRING) LIFECYCLE 1;
CREATE TABLE foo_t2(a STRING) LIFECYCLE 1;
@x := SELECT 'hello, world' AS a;
INSERT OVERWRITE TABLE foo_t1 SELECT * FROM @x;
INSERT INTO foo_t2 SELECT * FROM foo_t1 UNION ALL SELECT * FROM foo_t1;
SELECT * FROM foo_t2;
Örnek 3: Normal modda yazdıktan sonra okuma
Normal modda, aynı betik içinde bir tabloya yazıp ardından ondan okumak hataya neden olur. Bu örnek hatayı ve iki olası çözümü göstermektedir.
Veri hazırlığı
CREATE TABLE src(key BIGINT, value BIGINT) LIFECYCLE 1;
CREATE TABLE src2(key BIGINT, value BIGINT) LIFECYCLE 1;
INSERT INTO src VALUES(1, 2), (3, 3);
Hata örneği (normal modda yazdıktan sonra okuma)
INSERT OVERWRITE TABLE src2 SELECT * FROM src WHERE key > 0;
@a := SELECT * FROM src2; -- Error: src2 is written to and then read from in the same script.
SELECT * FROM @a;
Çözüm 1: Adım adım yürütme modunu etkinleştirin
SET odps.sql.step.script.mode=true;
INSERT OVERWRITE TABLE src2 SELECT * FROM src WHERE key > 0;
@a := SELECT * FROM src2;
SELECT * FROM @a;
Çözüm 2: SQL'i bir tablo değişkeni kullanacak şekilde yeniden yazın
@a := SELECT * FROM src WHERE key > 0;
INSERT OVERWRITE TABLE src2 SELECT * FROM @a;
SELECT * FROM @a;
Örnek 4: Geçici tablo oluşturma ve silme
Aşağıdaki betik, bir JOIN işleminin ara sonuçlarını önbelleğe almak için geçici bir tablo oluşturur, bu tablodan iki kez okur ve ardından tabloyu siler.
-- Enable step-by-step execution mode (required for temporary tables).
SET odps.sql.step.script.mode=true;
DROP TABLE IF EXISTS foo_t1;
CREATE TABLE foo_t1(a BIGINT, b BIGINT);
-- Create a temporary table by using a JOIN.
CREATE TEMPORARY TABLE t AS
SELECT t1.a AS a, t2.d AS b FROM
(SELECT 1 a, 2 b) t1
JOIN
(SELECT 1 c, 10 d) t2
ON t1.a = t2.c;
INSERT INTO foo_t1 SELECT * FROM t UNION ALL SELECT * FROM t;
SELECT * FROM foo_t1;
-- Drop the temporary table (must be the last statement in the script).
DROP TABLE t;
Betik Gönderme
Betik modu MaxCompute Studio, MaxCompute istemcisi (odpscmd), DataWorks ve Java ile Python SDK'larında desteklenir.
MaxCompute istemcisi (odpscmd)
odpscmd v0.27 veya sonraki bir sürümü kullanın. MaxCompute istemcisini yükledikten sonra, -s bayrağını kullanarak bir betik gönderin:
myscript.sql gibi bir betik dosyası oluşturun. Ardından, odpscmd'yi çalıştırmak için komut satırı arayüzünüzden aşağıdaki komutu çalıştırın. Komut satırından MaxCompute istemcisini çalıştırma hakkında daha fazla bilgi için bkz. MaxCompute istemcisini çalıştırma.
..\bin>odpscmd -s myscript.sql
odpscmd etkileşimli kabuğunda betik modu ve tablo değişkenleri desteklenmez. -s bayrağı, -f ve -e benzeri şekilde odpscmd için bir komut satırı seçeneğidir. Etkileşimli ortamda bir komut değildir.
DataWorks
DataWorks'te betikleri yazmak ve çalıştırmak için bir ODPS Script düğümü kullanın.
Sol üst köşede + Oluştur > Düğüm Oluştur seçeneğine tıklayın. MaxCompute kategorisi altında ODPS Script öğesini seçin.
Betik yazıldıktan sonra, araç çubuğundaki Run simgesine tıklayarak betiği yürütün. Çıktı günlüğü, yürütme planını ve sonuçları kontrol etmek için bir Logview URL'si içerir.
SDK'lar
SQL betiklerini doğrudan Java SDK veya Python SDK ile çalıştırın. Daha fazla bilgi için Java SDK ve Python SDK belgelerine bakın.
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.aliyun.odps.Instance;
import com.aliyun.odps.Odps;
import com.aliyun.odps.OdpsException;
import com.aliyun.odps.account.Account;
import com.aliyun.odps.account.AliyunAccount;
import com.aliyun.odps.data.Record;
import com.aliyun.odps.task.SQLTask;
public class SdkTest {
public static void main(String[] args) throws OdpsException {
// Your Alibaba Cloud AccessKey pair grants full access to your account and carries high risks.
// We strongly recommend that you create and use a RAM user for API calls and daily operations.
// To create a RAM user, log on to the RAM console.
// This example shows how to use environment variables to store your credentials.
// For security, never hard-code your AccessKey pair into your code.
Account account = new AliyunAccount(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
Odps odps = new Odps(account);
odps.setDefaultProject("your project_name");
odps.setEndpoint("your end_point");
String sqlScript = "@a := SELECT * FROM jdbc_test;\n"
+ "SELECT * FROM @a;";
// Required: Enable script mode.
Map<String, String> hints = new HashMap<>();
hints.put("odps.sql.submit.mode", "script");
Instance instance = SQLTask.run(odps, "your project_name", sqlScript, hints, null);
instance.waitForSuccess();
List<Record> recordList = SQLTask.getResult(instance);
for (Record record : recordList) {
System.out.println(record.get(0));
System.out.println(record.get(1));
}
}
}import os
from odps import ODPS
# Your Alibaba Cloud AccessKey pair grants full access to your account and carries high risks.
# We strongly recommend that you create and use a RAM user for API calls and daily operations.
# To create a RAM user, log on to the RAM console.
# This example shows how to use environment variables to store your credentials.
# For security, never hard-code your AccessKey pair into your code.
o = ODPS(
os.environ["ALIBABA_CLOUD_ACCESS_KEY_ID"],
os.environ["ALIBABA_CLOUD_ACCESS_KEY_SECRET"],
"your project_name",
"your end_point"
)
sql_script = """
@a := SELECT * FROM jdbc_test;
SELECT * FROM @a;
"""
# Required: Enable script mode.
hints = {"odps.sql.submit.mode", "script"}
instance = o.execute_sql(sql_script, hints=hints)
with instance.open_reader() as reader:
for rec in reader:
print(rec[0], rec[1])MaxCompute Studio
MaxCompute Studio'da bir betik çalıştırmadan önce aşağıdaki ön koşulları tamamlayın:
Betiği çalıştırdıktan sonra, betik birden fazla ifade içerse bile MaxCompute Studio yürütme planını tek bir DAG olarak görüntüler.