はじめに
進化し続けるデータベースの世界に、またひとつ心が熱くなるアップデートが加わりました。2025年9月25日――PostgreSQL 18のリリースとともに、「仮想生成列」という新しい機能が仲間入りしました。1
データは増えれば増えるほど、ストレージは膨らみ、INSERT は重くなります。その宿命に立ち向かうように現れたものが、この仮想生成列です。
そこで今回はデータ変換ツールDTRとPostgreSQLの「共演」が、果たして仮想生成列にも対応できるのかを検証してみました。DTRは入力データを読み取り、指定された定義に従って変換し、そして新しいカタチへと送り出すソフトウェアです。入力データが実在することが前提です。
「実体のない仮想生成列って、DTRでも扱えるの?」
この疑問を出発点に検証を始めました。
仮想生成列とは
仮想生成列(Virtual Generated Columns)は計算結果を保存しない生成列です。データベースを使っていると、「他の列から計算した値を自動で持っておいてほしいなぁ…」と思うことがあります。そのようなときに役立つものが生成列(Generated Columns)という仕組みです。
生成列とは、他の列を使って計算した結果が入っている列のことです。
たとえば注文テーブルに以下の項目があったとします。
- 単価
- 数量
ここに自動的に「単価 × 数量 = 合計金額」を計算してくれる列を作ることができます。アプリケーション側で合計金額を計算して入れる必要はなく、DBMS側が自動で計算してくれる便利な機能です。
PostgreSQL 12 で導入された生成列は格納生成列(Stored Generated Columns)です。これは計算結果をテーブルに実際に保存します。読む時は保存された値をそのまま取り出すだけです。
格納生成列にはメリットがありますが、デメリットもありました。
- 値が保存されるためにストレージを消費する
- レコード挿入時にDBMSが計算して保存するため、書き込み性能が落ちる
アプリケーションから書き込む値は減りますが、DBMS側の仕事は増えます。そこで仮想生成列です。計算結果を保存せず、読み取られた瞬間に計算され、必要な時だけ姿を現します。呼ばれた瞬間にふわっと現れて値を差し出してくれる妖精のような存在です。
保存しないため、ストレージは増えません。レコード書き込み時には計算されないため、書き込み性能は落ちません。それでも毎回、正しい計算済みの値が手に入る、便利な列です。とはいえ、何事も光あるところに影があります。仮想生成列は読み取り時に計算するため、読み取り性能は落ちます。まとめると以下の表になります。
| 項目 | 格納生成列 | 仮想生成列 |
|---|---|---|
| 登場 | PostgreSQL 12 | PostgreSQL 18 |
| データ保存 | 保存する | 保存しない |
| ストレージ | 増える | 増えない |
| 書き込み性能 | △ | ○ |
| 読み取り性能 | ○ | △ |
利用したソフトウェア
DTRのDB連携機能はODBCを利用します。そのため、ODBCドライバを導入し、ODBCデータソースを設定する必要があります。
やりたいこと
あなたはエフティーアドニャン 4 のキャラクターグッズのライセンサーです。
手元にはキャラクターグッズの注文データorder_ftadnyan.csvがあります。
項目は商品名(日本語)、商品名(英語)、数量、単価から構成されます。
エフティーアドニャンぬいぐるみ,FTADNYAN Plush Toy,101,800
エフティーアドニャンクリアファイル,ftadnyan clear file,32,300
エフティーアドニャン転送中ステッカー,FTAdnyan NOW Transferring Sticker,52,60
エフティーアドニャンTシャツ,FTADNYAN T-SHIRT,24,1200
エフティーアドニャンキーホルダー,ftadnyan keychain,42,250
エフティーアドニャン枕カバー,FTAdnyan Pillow cover,12,1300
エフティーアドニャンランチクロス,FTADNYAN LUNCH cloth,26,550
「商品名(英語)」は「FTADNYAN」「FTAdnyan」「ftadnyan」のように大文字・小文字が混在しています。これは現在のデータの欠陥であり、あなたは統一したいと考えています。
このデータを格納し、仮想生成列を追加したテーブルをPostgreSQLに作成します。以下のDDLを実行します。
CREATE TABLE order_ftadnyan(
item_ja varchar(100),
item_en varchar(100),
quantity int,
unit_price int,
item_en_norm varchar(100) GENERATED ALWAYS AS (initcap(item_en)),
total_amount numeric GENERATED ALWAYS AS (quantity * unit_price)
);
GENERATED ALWAYS ASのある項目が仮想生成列です。厳密には格納生成列が「GENERATED ALWAYS AS (式) STORED」、仮想生成列が「GENERATED ALWAYS AS (式) VIRTUAL」です。デフォルトはVIRTUALです。
仮想生成列item_en_normは項目「商品名(英語)」の各単語の先頭を大文字、それ以外を小文字に変換します。
仮想生成列total_amountは数量に単価を乗じて、合計金額を出します。
DB出力
それではDTRのDB出力機能を利用してCSVのデータをPostgreSQLに書き込みます。DTRのDB連携ではDB処理ファイルという二つの設定ファイルを作成します。
DB接続情報設定ファイルは以下内容です。
[Dtr_DBLink]
DSN=PostgreSQL35W
DSNにはODBCアドミニストレータで設定したデータソース名を指定します。「PostgreSQL35W」はデフォルトのデータソース名です。
DB接続ユーザやパスワードはODBCデータソースで設定したものを利用するため、今回のDB接続情報設定ファイルでは設定しません。
DB処理ファイルは以下内容です。
[DTR_DBLink]
SQL=INSERT INTO order_ftadnyan (item_ja, item_en, quantity, unit_price) VALUES (?, ?, ?, ?)
Transact=ALL
DeleteInsert=Y
以下のコマンドで実行します。
C:\dtr\dtrnt.exe '{m200 c100 s5 s5}' -V -A -S order_ftadnyan.csv -B access.ini proc_ins.ini
PostgreSQLでテーブルを参照してみます。CSV内容がPostgreSQLテーブルに書き込まれ、仮想生成列も表示されています。
postgres=# SELECT * from order_ftadnyan;
item_ja | item_en | quantity | unit_price | item_en_norm | total_amount
--------------------------------------+-----------------------------------+----------+------------+-----------------------------------+--------------
エフティーアドニャンぬいぐるみ | FTADNYAN Plush Toy | 101 | 800 | Ftadnyan Plush Toy | 80800
エフティーアドニャンクリアファイル | ftadnyan clear file | 32 | 300 | Ftadnyan Clear File | 9600
エフティーアドニャン転送中ステッカー | FTAdnyan NOW Transferring Sticker | 52 | 60 | Ftadnyan Now Transferring Sticker | 3120
エフティーアドニャンTシャツ | FTADNYAN T-SHIRT | 24 | 1200 | Ftadnyan T-Shirt | 28800
エフティーアドニャンキーホルダー | ftadnyan keychain | 42 | 250 | Ftadnyan Keychain | 10500
エフティーアドニャン枕カバー | FTAdnyan Pillow cover | 12 | 1300 | Ftadnyan Pillow Cover | 15600
エフティーアドニャンランチクロス | FTADNYAN LUNCH cloth | 26 | 550 | Ftadnyan Lunch Cloth | 14300
(7 行)
DB入力
続いてDTRのDB入力機能を利用して仮想生成列を含むテーブルの内容をCSVファイルに出力します。
DB接続情報設定ファイルはDB出力と同じものを利用します。
DB処理ファイルは以下内容です。
[DTR_DBLink]
SQL=select item_ja, item_en_norm, quantity, unit_price, total_amount from order_
ftadnyan
項目item_enの代わりに単語の先頭を大文字に統一した仮想生成列item_en_normを出力します。また、合計金額の仮想生成列total_amountも出力します。
以下のコマンドで実行します。
C:\dtr\dtrnt.exe '{m200 c100 s5 s5 c10}' -B access.ini proc_sel.ini -V -A -S order_ftadnyan_virtual.csv
以下のCSVファイルが出力されました。
エフティーアドニャンぬいぐるみ,Ftadnyan Plush Toy,101,800,80800
エフティーアドニャンクリアファイル,Ftadnyan Clear File,32,300,9600
エフティーアドニャン転送中ステッカー,Ftadnyan Now Transferring Sticker,52,60,3120
エフティーアドニャンTシャツ,Ftadnyan T-Shirt,24,1200,28800
エフティーアドニャンキーホルダー,Ftadnyan Keychain,42,250,10500
エフティーアドニャン枕カバー,Ftadnyan Pillow Cover,12,1300,15600
エフティーアドニャンランチクロス,Ftadnyan Lunch Cloth,26,550,14300
「商品名(英語)」の項目は単語の先頭が大文字、それ以外は小文字になっています。また、数量に単価を乗じた合計金額も出力されています。
まとめ
今回の検証で、DTRはPostgreSQLの仮想生成列も読み取れることが分かりました。保存されない列、でも必要な瞬間には確かに姿を見せてくれる――そんな「軽やかな列」の働きは、ストレージにも書き込み性能にも負担をかけない、優しい設計です。テーブルサイズを膨らませることなく、書き込み性能を守り抜くその姿勢に、思わず「これだよ、求めてたのは」と頷いてしまいます。
DTRとPostgreSQLを組み合わせることで乱れたデータを整え、必要な形に再生し、次の処理へと気持ちよくバトンを渡すことができます。データクレンジングの可能性がさらに広がり、より洗練されたデータ管理が実現します。
We Are Hiring!
-
PostgreSQL 18 Released!
https://www.postgresql.org/about/news/postgresql-18-released-3142/ ↩ -
DTRIIはWindows版の商品名です。詳細は、以下をご覧ください。
https://www.biprogy.com/solution/service/dtr.html ↩ -
PostgreSQLのODBC ドライバ(psqlODBC)はバージョン17系が2026年3月時点も最新として配布されています。REL-17_00_0007-mimallocはPostgreSQL 18リリース後の2025年11月24日にリリースされました。
https://www.postgresql.org/ftp/odbc/releases/ ↩ -
エフティーアドニャンは、ファイル転送を見守る「ファイルの妖精」という設定の架空のキャラクターです。私のアイコン画像のキャラクターです。 ↩