pgAdminを使ってRDS for PostgreSQLのロケール設定を変更する

この記事を書いたメンバー:

榊原慶太

pgAdminを使ってRDS for PostgreSQLのロケール設定を変更する

目次

ハイブリッドクラウドコンサルティング部の榊原です。
今回はRDS for PostgreSQLのロケール設定を変更する方法を述べます。
前回の記事ではPgAdminを使ってRDSにアクセスし、データベースを操作する方法について述べているので、ご興味がある方はそちらも併せて読んでいただければと思います。

本記事の前提

・PostgreSQLのエンジンバージョンは15.4-R1
・pgAdminで既にRDSインスタンスに接続できる状態(pgAdmin無しでも解決可能)

発生した事象

RDSインスタンス内部のデータベース対してORDER BYでname列のデータを並び替えた際、表示されるデータの順番があいうえお順になっておらず不自然です。下記画像はname列の値を基にソートを書けたものですが、統一感がありません。(データの中身は最近の検索履歴からとりました)

詳細説明

結論から言うと、PostgreSQLのロケール設定がCでなかったことが原因でした。
具体的な修正案に移る前にロケールの説明から入ります。

ロケールとは

ロケールの説明や設定については、こちらのページから引用します。

PostgreSQL でロケール (国際化と地域化) の設定を行うと、データベース内での文字列処理、日付や通貨の表示、メッセージの言語などを変更することができます。特に PostgreSQL 8.4 では、日本語のメッセージ・カタログが追加されたため、エラーメッセージを日本語化したい場合にはロケールを設定する必要があります。

ただし、C ロケール以外を設定すると、インデックスが使われないなどの性能への影響がある場合もあります。また、特に古いバージョンの PostgreSQL では、誤った設定によりサーバが正しく動作しなくなるケースもありました。

PostgreSQL の利用者の間では「ロケールを C に設定する」ことを「ロケールを設定しない」と表現する場合がありますが、どちらも同じ意味です。initdb コマンドでも --locale=C と --no-locale は同じ意味ですね。

また、PostgreSQL15.4のドキュメントには以下のような記載があります。

実行環境のロケールをそのまま使用するということは、ほとんどのオペレーティングシステムでは次のような意味を持ちます。 指定されたロケールカテゴリ(例えば照合順序)について、設定するものが見つかるまで、以下の環境変数がこの順番で調べられます。LC_ALLLC_COLLATE(またはそれぞれのカテゴリに対応する変数)、LANG。 これらのいずれの環境変数も設定されない場合に、ロケールはデフォルトでCに設定されます。

設定すべきロケールの項目ですが以下の通りです。(PostgreSQL15.4のドキュメントからの引用)

LC_COLLATE文字列の並び替え順
LC_CTYPE文字の分類(文字とはどんなもの?大文字小文字を区別しない?)
LC_MESSAGESメッセージの言語
LC_MONETARY通貨書式
LC_NUMERIC数字の書式
LC_TIME日付と時刻の書式

以上の記述から、DBに対して何か特別な要件が無い限りはロケールはCに設定するのがよさそうです。そして表の6項目をCにすることで、ORDER_BYがうまく機能することが期待できます。
ざっくりですがロケール周りの説明は以上です。

検証

実際に修正する前のロケールの設定は下記の通りでした。
LC_COLLATE、LC_CTYPE、LC_MESSAGESがCになっていません。

パラメータグループを変える

LC_MESSAGESはパラメータグループで変更することが可能です。初期状態ではデフォルトのパラメータグループを付けていました。なので新規でパラメータグループを作成し、「LC_」とつくパラメータを全てCに設定します。LC_COLLATE、LC_CTYPEの値についてはパラメータグループで設定できません。

lc_messagesC
lc_monetaryC
lc_numericC
lc_timeC

編集したパラメータグループをRDSインスタンスに反映します。変更時「すぐに適用」を選択してステータスが「利用可能」になっても、インスタンスの再起動が必要なので注意してください。

インスタンスを再起動したら、次に進みます。

新規DB作成(LC_COLLATEとLC_CTYPEの設定変更)

残るLC_COLLATEとLC_CTYPEの設定を行います。
PostgreSQL15.4のドキュメントを見ると以下のような記述があります。

LC_COLLATEとLC_CTYPEの設定はデータベース作成時に決定され、新しいデータベースを作成する方法以外に変更することはできません。

とのことですので、ここからは新規データベースを作成します。今回はせっかくなのでSQL文を直接書かず、pgAdminを使用してDBを作成します。

pgAdminを開き、
Servers(右クリック)
>Register
>Server...
の順に押します。

データベース名は任意のものでOKです。

次に下記操作を行います
「Definition」を押す
>「Template」で「template0」を選択
>「Locale Provider」で「libc」を選択
>「Collation」で「C」を選択
>「Character type」で「C」を選択
ここまで終えたら「Save」を押します。

お気づきの方もいらっしゃるかと思いますが、CollationとはLC_COLLATE、Character typeとはLC_CTYPEと対応しており、二つともCと設定しています。これでロケールの設定は完了です。ちなみにtemplate0についてですが、PostgreSQL15.4のドキュメントを見ると以下のような記述があります。

実際のCREATE DATABASEの動作は、既存のデータベースをコピーすることです。 デフォルトでは、template1という名前の標準のシステムデータベースをコピーします。

template1template0には、template1という名前がCREATE DATABASEのデフォルトのソースデータベースの名前であること以上の特別な地位はありません。 例えば、template1を削除し、template0から再作成しても何も問題ありません。 

template1の代わりにtemplate0をコピーするその他の一般的な理由は、template0をコピーするときに新規の符号化方式とロケールを設定できることです。

なので今回Templateにはtemplate0を指定しています。
また、Local_providerにはlibcを指定しています。再びPostgreSQL15.4のドキュメントを見てみると以下のような記述があります。

PostgreSQLは複数のロケールプロバイダをサポートします。 これによってどのライブラリがロケールデータを提供するかを決定します。 標準プロバイダの一つはlibcで、オペレーティングシステムのCライブラリが提供するロケールを使用します。

ロケール設定が正しくなっているか確認します。大丈夫そうです。

ソートが正しく機能しているか確認

冒頭でお見せしたデータが正しく並び替えられるようになったか確認します。結果は以下の通りでした。

アルファベットが前に来て、そのあとの日本語ワードはカタカナ、漢字という並びになっています。カタカナ部分については最初に比べ、自然な並びになりました。なお、漢字についてはこちらのサイトで以下のような記述がありました。

(ロケールをCにした時のメリットについて)ひらがな、カタカナ、濁音などのソート順序が辞書順になります。ただ、もちろん漢字の読み方までは考慮してくれませんので、全てひらがなに統一した「読み仮名」列を用意して比較するほうが確実ではあります。

読み仮名列を加えれば、漢字だけでなく英語も含んでアルファベット順で表示することが出来そうです。今回の検証は以上とします。

最後に

今回はRDS for PostgreSQLのロケールの設定とpgAdminを絡めてお話ししました。最近はRDSを構築するだけで終わらず、その中の仕組みまで調査することが徐々に増えてきました。インフラを軸に徐々にこういったミドルウェアの中身まで理解して扱えるようになりたいです。ここまでお読みいただきありがとうございました。

カテゴリー

この記事を書いたメンバー

榊原慶太
榊原慶太

技術検証、re:Invent参加、AWS資格全冠のための勉強教材等、幅広く記事にしています。皆様のお役に立てば幸いです。最近は会社ブログメインで記事投稿しています。

SAPシステムや基幹システムのクラウド移行・構築・保守、
DXに関して
お気軽にご相談ください

03-6260-6240 (受付時間 平日9:30〜18:00)