目次
ハイブリッドクラウドコンサルティング部の榊原です。
今回は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_ALL
、LC_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_messages | C |
lc_monetary | C |
lc_numeric | C |
lc_time | C |
編集したパラメータグループを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
という名前の標準のシステムデータベースをコピーします。
template1
とtemplate0
には、template1
という名前がCREATE DATABASE
のデフォルトのソースデータベースの名前であること以上の特別な地位はありません。 例えば、template1
を削除し、template0
から再作成しても何も問題ありません。
template1
の代わりにtemplate0
をコピーするその他の一般的な理由は、template0
をコピーするときに新規の符号化方式とロケールを設定できることです。
なので今回Templateにはtemplate0を指定しています。
また、Local_providerにはlibcを指定しています。再びPostgreSQL15.4のドキュメントを見てみると以下のような記述があります。
PostgreSQLは複数のロケールプロバイダをサポートします。 これによってどのライブラリがロケールデータを提供するかを決定します。 標準プロバイダの一つは
libc
で、オペレーティングシステムのCライブラリが提供するロケールを使用します。
ロケール設定が正しくなっているか確認します。大丈夫そうです。
ソートが正しく機能しているか確認
冒頭でお見せしたデータが正しく並び替えられるようになったか確認します。結果は以下の通りでした。
アルファベットが前に来て、そのあとの日本語ワードはカタカナ、漢字という並びになっています。カタカナ部分については最初に比べ、自然な並びになりました。なお、漢字についてはこちらのサイトで以下のような記述がありました。
(ロケールをCにした時のメリットについて)ひらがな、カタカナ、濁音などのソート順序が辞書順になります。ただ、もちろん漢字の読み方までは考慮してくれませんので、全てひらがなに統一した「読み仮名」列を用意して比較するほうが確実ではあります。
読み仮名列を加えれば、漢字だけでなく英語も含んでアルファベット順で表示することが出来そうです。今回の検証は以上とします。
最後に
今回はRDS for PostgreSQLのロケールの設定とpgAdminを絡めてお話ししました。最近はRDSを構築するだけで終わらず、その中の仕組みまで調査することが徐々に増えてきました。インフラを軸に徐々にこういったミドルウェアの中身まで理解して扱えるようになりたいです。ここまでお読みいただきありがとうございました。
- カテゴリー