Tüm Ürünler
Search
Belge Merkezi

MaxCompute:İşlem hattı örnekleri

Son Güncelleme:Oct 04, 2026

Bu örnekte, MaxCompute MapReduce Pipeline işi kullanılarak kelime sıklıklarının nasıl sayılacağı gösterilmektedir. İşlem hattı, bir mapper (TokenizerMapper) ile iki reducer'ı (SumReducer ve IdentityReducer) birbirine bağlar; böylece Pipeline API'nin birden çok işleme aşamasını tek bir işte nasıl birleştirdiği ortaya konur.

Ön koşullar

Başlamadan önce aşağıdakileri tamamladığınızdan emin olun:

Test kaynaklarını hazırlayın

1. JAR paketini hazırlayın

mapreduce-examples.jar dosyasını MaxCompute istemci kurulumunuzun bin\data\resources dizinine yerleştirin.

2. Tabloları oluşturun

MaxCompute istemcisinde aşağıdaki SQL deyimlerini çalıştırın:

CREATE TABLE wc_in (key STRING, value STRING);
CREATE TABLE wc_out(key STRING, cnt BIGINT);

3. JAR paketini kaynak olarak ekleyin

add jar data\resources\mapreduce-examples.jar -f;
-f bayrağı, aynı ada sahip mevcut bir kaynağın üzerine yazar. JAR paketini ilk kez eklerken bu bayrağı atlayın.

4. Test verilerini içe aktarın

MaxCompute istemcisinin bin dizinindeki data.txt dosyasını wc_in tablosuna yüklemek için bir Tunnel komutu kullanın:

tunnel upload data.txt wc_in;

data.txt dosyası aşağıdaki satırı içerir:

hello,odps

İşlem hattını çalıştırın

MaxCompute istemcisinde aşağıdaki komutu çalıştırın:

jar -resources mapreduce-examples.jar -classpath data\resources\mapreduce-examples.jar
com.aliyun.odps.mapred.open.example.WordCountPipeline wc_in wc_out;

Sonucu doğrulayın

İş tamamlandıktan sonra çıktıyı onaylamak için wc_out tablosunu sorgulayın:

SELECT * FROM wc_out;

Beklenen çıktı şöyledir:

+------------+------------+
| key        | cnt        |
+------------+------------+
| hello      | 1          |
| odps       | 1          |
+------------+------------+

Örnek kod

Project Object Model (POM) bağımlılık yapılandırması için Precautions bölümüne bakın.

İşlem hattının çalışma şekli

İşlem hattı üç aşamadan oluşur. Her aşama verileri aşağıdaki gibi dönüştürür:

wc_in (key STRING, value STRING) → TokenizerMapper → (word STRING, count BIGINT) → SumReducer → (word STRING, count BIGINT) → IdentityReducer → wc_out (key STRING, cnt BIGINT)


Sınıf


Rol


TokenizerMapper


Her kaydı belirteçlere ayırır ve her belirteç için (word, 1) çiftini yayar


SumReducer


Her kelime anahtarı için sayıları toplar


IdentityReducer


Son (word, count) çiftlerini çıktı tablosuna yazar

İki reducer'lı tasarım, toplamayı çıktı biçimlendirmesinden ayırır. SumReducer tüm mapper çıktılarındaki toplamları biriktirir. IdentityReducer ise ara şemayı wc_out tablo şemasına eşleyerek iki sorumluluğu bağımsız tutar; bu sayede her reducer'ın test edilmesi ve değiştirilmesi kolaylaşır.

İşlem hattı oluşturulurken bir mapper için OutputKeySortColumns , PartitionColumns ve OutputGroupingColumns belirtilmezse çerçeve, mapper'ın OutputKey değerini bu üç parametre için varsayılan olarak kullanır.

Java kodu

package com.aliyun.odps.mapred.open.example;
import java.io.IOException;
import java.util.Iterator;
import com.aliyun.odps.Column;
import com.aliyun.odps.OdpsException;
import com.aliyun.odps.OdpsType;
import com.aliyun.odps.data.Record;
import com.aliyun.odps.data.TableInfo;
import com.aliyun.odps.mapred.Job;
import com.aliyun.odps.mapred.MapperBase;
import com.aliyun.odps.mapred.ReducerBase;
import com.aliyun.odps.pipeline.Pipeline;
public class WordCountPipelineTest {
    public static class TokenizerMapper extends MapperBase {
        Record word;
        Record one;
        @Override
            public void setup(TaskContext context) throws IOException {
            word = context.createMapOutputKeyRecord();
            one = context.createMapOutputValueRecord();
            one.setBigint(0, 1L);
        }
        @Override
            public void map(long recordNum, Record record, TaskContext context)
            throws IOException {
            for (int i = 0; i < record.getColumnCount(); i++) {
                String[] words = record.get(i).toString().split("\\s+");
                for (String w : words) {
                    word.setString(0, w);
                    context.write(word, one);
                }
            }
        }
    }
    public static class SumReducer extends ReducerBase {
        private Record value;
        @Override
            public void setup(TaskContext context) throws IOException {
            value = context.createOutputValueRecord();
        }
        @Override
            public void reduce(Record key, Iterator<Record> values, TaskContext context)
            throws IOException {
            long count = 0;
            while (values.hasNext()) {
                Record val = values.next();
                count += (Long) val.get(0);
            }
            value.set(0, count);
            context.write(key, value);
        }
    }
    public static class IdentityReducer extends ReducerBase {
        private Record result;
        @Override
            public void setup(TaskContext context) throws IOException {
            result = context.createOutputRecord();
        }
        @Override
            public void reduce(Record key, Iterator<Record> values, TaskContext context)
            throws IOException {
            while (values.hasNext()) {
                result.set(0, key.get(0));
                result.set(1, values.next().get(0));
                context.write(result);
            }
        }
    }
    public static void main(String[] args) throws OdpsException {
        if (args.length != 2) {
            System.err.println("Usage: WordCountPipeline <in_table> <out_table>");
            System.exit(2);
        }
        Job job = new Job();
        /** During pipeline construction, if you do not specify OutputKeySortColumns, PartitionColumns, and OutputGroupingColumns for a mapper, the framework uses OutputKey of the mapper as the default values of these parameters.
         */
        Pipeline pipeline = Pipeline.builder()
            .addMapper(TokenizerMapper.class)
            .setOutputKeySchema(
            new Column[] { new Column("word", OdpsType.STRING) })
            .setOutputValueSchema(
            new Column[] { new Column("count", OdpsType.BIGINT) })
            .setOutputKeySortColumns(new String[] { "word" })
            .setPartitionColumns(new String[] { "word" })
            .setOutputGroupingColumns(new String[] { "word" })
            .addReducer(SumReducer.class)
            .setOutputKeySchema(
            new Column[] { new Column("word", OdpsType.STRING) })
            .setOutputValueSchema(
            new Column[] { new Column("count", OdpsType.BIGINT)})
            .addReducer(IdentityReducer.class).createPipeline();
        /** Add the pipeline to jobconf. If you want to configure a combiner, use jobconf. */
        job.setPipeline(pipeline);
        /** Configure the input and output tables. */
        job.addInput(TableInfo.builder().tableName(args[0]).build());
        job.addOutput(TableInfo.builder().tableName(args[1]).build());
        /** Submit the job and wait for it to complete. */
        job.submit();
        job.waitForCompletion();
        System.exit(job.isSuccessful() == true ? 0 : 1);
    }
}

Veri akışı incelemesi

Giriş verisi hello,odps olduğunda Tunnel komutu bu veriyi tek bir kayıt olarak wc_in tablosuna yükler; hello değerini key sütununa, odps değerini ise value sütununa kaydeder.

TokenizerMapper, record.getColumnCount() kullanarak her kaydın tüm sütunları üzerinde yineleme yapar. Her sütun değeri için split("\\s+") çağrısı yapar ve her belirteç için bir (word, 1) çifti yayar. hello ve odps değerlerinde boşluk karakteri bulunmadığından her biri tek bir belirteç olarak değerlendirilir. Mapper şu çıktıyı üretir:

(hello, 1)
(odps, 1)

SumReducer, her kelime anahtarı için gelen tüm değerleri alır ve sayıları toplar. Her kelime yalnızca bir kez göründüğünden reducer şu çıktıyı verir:

(hello, 1)
(odps, 1)

IdentityReducer, SumReducer aşamasından gelen (word, count) çiftlerini okur ve bunları wc_out çıktı tablosuna yazar; sütun konumlarını (key STRING, cnt BIGINT) şemasıyla eşleşecek şekilde haritalandırır.

wc_out tablosundaki son çıktı:

| hello      | 1          |
| odps       | 1          |