CData Software Blog

クラウド連携のCData Software の技術ブログです。

API Server : SQL Serverでインデックス化されたカラムのフィルタリングを高速化する

こんにちは。 CData Software Japan エンジニアの浦邊です。 この記事はQiita CData Software Advent Calendar 2021 16日目の記事になります。

qiita.com

API Serverで作成したAPIに対してGETでデータを取得する際にフィルタ条件を指定することができます。 例えば製品情報を取得するAPIhttp://MyServer/api.rsc/Productsに対し、Nameフィールドが「Product 1」というレコードのみを取得するときは以下のようにURLの中にフィルタ条件を指定します。

http://MyServer/api.rsc/Products(Name='Product 1')

当然ながらレコードが大量にあるテーブルに対してフィルタ条件を指定したリクエストを実行するとレスポンスに長い時間がかかります。 このようなリクエストではフィルタ対象のカラムにインデックスを設定することで読み込みをある程度高速化できます。

しかし実はまだ性能改善の余地が残されています。 API Serverが使用するSQL Serverドライバは(デフォルトの挙動として)フィルタ条件に指定されたパラメータ値をUnicode文字列(NVARCHAR)として読み込み、インデックス対象のカラムと照合する際もUnicode文字列として比較します。 これはカラムの型がNVARCHARかVARCHARかは関係ありません。

しかし、Unicodeを前提としないVARCHAR型のカラムをUnicode文字列として読み込むのは無駄なような気がします。 そこで、API Serverではフィルタ条件のパラメータ値をUnicodeとして読むかどうかを制御するプロパティがあります。 これをオフにするとパラメータ値を非Unicode文字列(VARCHAR)として読み込みます。 インデックス対象のカラムに対して非Unicode文字列で照合するため、レスポンス時間を大幅に短縮することができます。

本記事ではプロパティの設定方法と、性能に与える影響を評価した結果を示します。

設定方法

方法は簡単で、あるプロパティを設定するだけです。 以下にAPI Server Windows EditionとJava Editionでそれぞれ設定方法を示します。

API Server Windows Edition

設定ファイル(C:\ProgramData\CData\apiserver\settings.cfg)に以下のプロパティを追加します。

UseUnicodeString = false

設定例

f:id:urabe_shintaro:20211216162005p:plain

API Serverの再起動は必要ありません。

API Server Java Edition

SQL Serverの接続を作成する際、接続プロパティにSendStringParametersAsUnicode=falseを追加します。

f:id:urabe_shintaro:20211216152614p:plain

性能比較

本プロパティでどれくらい性能が改善するか実験しました。 実験では以下のスキーマを利用しました。

テストテーブルのスキーマ

Productsテーブル

カラム名 タイプ
Id integer
Name* varchar(2000)

*カラムNameにはインデックスを作成しています。

3000万件のデータを用意し、以下のようにfilterパラメータを付与したリクエストを実行しました。

http://localhost:8080/api.rsc/Products$filter=Name%20eq%20%27Product%20A%27

Windows Edition, Java Editionでそれぞれ実行した結果を以下に示します。 どちらもプロパティの設定のみで劇的に性能が改善したことが分かります。

f:id:urabe_shintaro:20211216171259p:plain

なお、この実験ではVARCHARのカラムを対象としましたがNVARCHARのカラムに対しても同様の効果があります。 ただしUnicodeの文字列が含まれていないことに注意してください。

まとめ

本記事ではSQL Serverでインデックス化されたカラムのフィルタリングを高速化するプロパティを紹介しました。 SQL Serverで大量のレコードを扱う際にぜひお試しください。