Skip to content
Last updated

Presto 0 205から317へのマイグレーション 2020

Treasure DataのPrestoリリースは、Presto 317のオープンソースリリースに基づいています。以前のリリースはPresto 0.205に基づいていました。この記事には以下が含まれます:

互換性とパフォーマンスの退行問題を特定するため、社内テストを実施しました。

新しいマジックコメント機能

parse_decimal_literals_as_double

parse_decimal_literals_as_double セッションプロパティは、マジックコメントとしてサポートされています。

明示的な型指定子を持たない10進リテラル(例: 1.2)は、デフォルトでDOUBLE型の値として扱われます。

このマジックコメントを使用すると、この動作を無効化し、10進リテラルをDECIMAL型の値として使用できます。例:

-- set session parse_decimal_literals_as_double = 'false'
    SELECT typeof(1.1);

Distributed_Sort

distributed_sort セッションプロパティは、マジックコメントとしてサポートされています。

分散ソートを使用すると、query.max-memory-per-nodeを超えるデータのソートが可能になります。分散ソートは、distributed_sortセッションプロパティ、またはコーディネーターのetc/config.propertiesに設定されたdistributed-sort設定プロパティを通じて有効化されます。分散ソートはデフォルトで有効になっています。

分散ソートが有効な場合、ソート演算子はクラスター内の複数のノードで並列実行されます。各ワーカーノードから部分的にソートされたデータは、最終的なマージのために単一のワーカーノードにストリーミングされます。この手法により、ソートのために複数のワーカーノードのメモリを活用できます。分散ソートの主な目的は、通常は単一ノードのメモリに収まらないデータセットのソートを可能にすることです。パフォーマンスの向上が期待できますが、データを単一ノードでマージする必要があるため、ノード数に対して線形にスケールすることはありません。

-- set session distributed_sort = 'true'
    SELECT * FROM large_table, small_table
    WHERE small_table.id = large_table.id

time_partitioning_range

time_partitioning_rangeセッションプロパティは、マジックコメントとしてサポートされています。

-- set session time_partitioning_range = 'value`

値は以下のいずれかです

  * none

    * タイムパーティショニングなし

  * 単位付きの数値

    * 許可される単位は`h, d, mo, q, y` (時間、日、月、四半期、年)

    * 例) 12h, 2d, 1mo, 1q, 1y

# 非推奨の機能

## 分散結合のマイグレーション

**distributed_join** セッションプロパティは削除されました。

代わりに**join_distribution_type** セッションプロパティを使用してください。**join_distribution_type** システムプロパティは、以下の値を受け付けます:

  * PARTITIONED

  * BROADCAST

非推奨のコード:

```sql
-- set session distributed_join = 'true'
    SELECT * FROM large_table, small_table
    WHERE small_table.id = large_table.id

更新されたコード:

```sql
-- set session join_distribution_type = 'PARTITIONED'
    SELECT *
    FROM large_table, small_table
    WHERE small_table.id = large_table.id

Prestoの更新

サイドバイサイド環境について

テストのため、Presto 0.205とPresto 317がサイドバイサイドで利用可能であり、アップグレード前にコードのテストが可能です。

Presto 317とPresto 0.205でのコード実行

Presto 317とPresto 0.205からの移行期間中、2つのリリースがサイドバイサイドで利用可能です。

以下のクエリヒントを使用して、どのPrestoリリースでコードを実行するかを制御できます:

バージョンクエリヒント
Presto 317-- @TD engine_version: 317
Presto 0.205-- @TD engine_version: 0.205

クエリ構文の修正

以前のバージョンで動作していたクエリを実行すると、エラーメッセージが発生する場合があります。各ケースについて、メッセージ、エラーを引き起こすクエリ、およびクエリの書き換え方法の例を示します。

ORの述語が多すぎます。最大500個のORが許可されています

エラーの原因となる元のコード:

SELECT path FROM  (
     SELECT * FROM sample_datasets.www_access ) WHERE
    path = 'foo1' OR path = 'foo2' OR path = 'foo3'
    -- Query having a lot of "OR" clauses
    OR path = 'foo559';

エラーを修正したコード:

SELECT path FROM (
     SELECT * FROM sample_datasets.www_access ) WHERE
    path IN (
     'foo1', 'foo2', 'foo3' ,
    -- Query having a lot of conditions
    'foo559');

通常、IN句を使用してクエリを書き直すことで、この問題は解決されます。

Key not present in map: XXX

エラーの原因となる元のコード:

SELECT MAP(ARRAY [1, 3], ARRAY [2, 4])[5];

エラーを修正したコード:

SELECT element_at(MAP(ARRAY [1, 3], ARRAY [2, 4]), 5);

クエリを書き直すには、関数element_atを使用できます。関数element_atは、v0.205とv317の両方のクラスターバージョンでサポートされています。前述のクエリは両方のクラスターで実行できます。

Array subscript out of bounds

エラーの原因となる元のコード:

SELECT
     numbers[99] -- key isn't exist
    FROM
     (VALUES (ARRAY[1,2,3]) ) AS t(numbers);

エラーを修正したコード:

SELECT
      element_at(numbers, 99) -- key isn't exist
    FROM
      (VALUES (ARRAY[1,2,3]) ) AS t(numbers);

関数element_atは、v0.205とv317の両方のクラスターバージョンでサポートされています。

前述のクエリは両方のクラスターで実行できます。

Column alias list has 1 entry but 't' has N columns available'

エラーの原因となる元のコード:

WITH
    dataset AS (
     SELECT ARRAY[
     CAST(ROW('Amy', 'devops') AS ROW(name VARCHAR, department VARCHAR))
     ] AS users
    ),
    u AS (
     SELECT person
     FROM
     dataset,
     UNNEST(dataset.users) AS t(person)
     )
    SELECT
     person.name,
     person.department
    FROM u;

エラーを修正したコード:

WITH
    dataset AS (
     SELECT ARRAY[
     CAST(ROW('Amy', 'devops') AS ROW(name VARCHAR, department VARCHAR))
     ] AS users
    ),
    u AS (
     SELECT
     name, department
     FROM
     dataset,
     UNNEST(dataset.users) AS person(name, department)
     )
    SELECT
     name,
     department
    FROM u;

Window does not support distinct

エラーの原因となる元のコード:

SELECT
      UPPER(DISTINCT(id)) AS user_id
    FROM (VALUES ('foo'), ('bar')) AS t(id);

エラーを修正したコード:

SELECT
      UPPER(id) AS user_id
    FROM (
      SELECT DISTINCT id FROM (VALUES ('foo'), ('bar')
    ) AS t (id));

## null要素を含む配列の配列比較はサポートされていません

エラーを引き起こす元のコード:

```sql
SELECT id, array_agg(value)
    FROM (
     VALUES
     (1, 3), (1, 4), (1, 5), (2, 6), (2, 7), (3, null)
    ) AS t(id, value)
    GROUP BY 1 ORDER BY 2;

エラーを修正したコード:

SELECT id, array_agg(value) FILTER (where value is not null)
    FROM (
     VALUES
     (1, 3), (1, 4), (1, 5), (2, 6), (2, 7), (3, null)
    ) AS t(id, value)
    GROUP BY 1 ORDER BY 2;

関数element_atは、両方のクラスターバージョン、v0.205とv317でサポートされています。上記のクエリは両方のクラスターで実行されます。

このエラーの詳細: array_agg関数の動作変更

Presto 0.205では、array_agg関数はNULL値を無視します。

presto> SELECT id, array_agg(value) FROM ( VALUES (1, null), (1, 0) ) AS t(id, value) GROUP BY 1;
    id | _col1
   ----+-------
    1 | [0]
   (1 row)

   presto> SELECT id, array_agg(value) FROM ( VALUES (1, null) ) AS t(id, value) GROUP BY 1;
    id | _col1
   ----+-------
    1 | NULL
   (1 row)

Presto 0.205では、array_agg関数のこのレガシー動作を維持するために、_deprecated_._legacyagg_プロパティがtrueに設定されています。

このプロパティはPresto 317で削除され、レガシー動作をロールバックする機能はありません。

Presto 317では、array_agg関数はNULL値を無視せず、NULL値を含む配列を返します。

presto> SELECT id, array_agg(value) FROM ( VALUES (1, null), (1, 0) ) AS t(id, value) GROUP BY 1; id | _col1 ----+----------- 1 | [null, 0] (1 row)

presto> SELECT id, array_agg(value) FROM ( VALUES (1, null) ) AS t(id, value) GROUP BY 1; id | _col1 ----+-------- 1 | [null] (1 row)

その結果、PrestoがNULL値を含む配列を持つカラムと比較を行うと、PrestoはARRAY comparison not supported for arrays with null elementsというメッセージを返します。

'XXX' must be an aggregate expression or appear in a GROUP BY clause

エラーを引き起こす元のコード:

SELECT code FROM sample_datasets.www_access
    HAVING code IS NOT NULL;

エラーを修正したコード:

SELECT code FROM sample_datasets.www_access
    WHERE code IS NOT NULL;

HAVING句をWHERE句として使用すると、このエラーが表示されます。

Zero-length delimited identifier not allowed

エラーを引き起こす元のコード:

SELECT 1 AS "";

エラーを修正したコード:

SELECT 1 AS "A";

Unexpected parameters (char(1)) for function codepoint. Expected: codepoint(varchar(1))

エラーを引き起こす元のコード:

SELECT codepoint(CAST('a' AS CHAR));

エラーを修正したコード:

SELECT codepoint(CAST('a' AS VARCHAR(1)));

Invalid format: "XXX" is malformed / Invalid timezone: "XXX" is malformed

v317ではエラー処理が改善されました。無効な引数が渡された場合、現在のPrestoはNULLを返しますが、新しいPrestoはエラーを返します。

エラーを引き起こす元のコード:

SELECT td_time_range(1567890000, 'yyyy-MM-dd','JST', NULL);

エラーを修正したコード:

SELECT td_time_range(1567890000, '2019-09-08', 'JST', NULL);