最近、私はこのようなスロークエリを監視しました:
delete_flag、delete_timefrom d_orderinfoを選択します(orderidはnull and orderid = n'xxxx ')
D_ORDERINFOテーブルにはOrderIDのインデックスがありますが、OrderIDフィールドは型VARCHARです。
開発フレームワークMyBatisはWhere条件を自動的に生成し、パラメータータイプを指定しないため、文字列型のパラメーターはSQLServerで自動的にNvarChar(4000)になります。トリッキーなのは、パラメータータイプを指定しない場合は問題ないことですが、OrderIDがnullではないような非Sarg条件を自動的に追加することも、実行計画が次のようになります。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
OrderIDがnull条件でない場合、実行計画は次のようになります。
パラメータータイプのnvarcharはインデックスフィールドタイプのVarcharよりも優先度が高いため、直接変換することはできませんが、SQLServer Optimizerは最終的に範囲値に変換し、最終的な等記号クエリは小さな範囲クエリに似ています。
インデックスシークの詳細情報から確認できます。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
パラメータータイプが一致する場合、実行計画は予想通りになります(含まれていませんが、まだ重要な検索があります):
もちろん、私がついに書きたいと思った方法は次のとおりです。
delete_flag、delete_timefrom d_orderinfo where orderid = 'xxxx'を選択します
もちろん、実行計画は次のようになります。
しかし、私は開発マスターが最終的に何に変わることができるかわかりません...
開発マスターのソリューション:接続文字列を構成します:
SendStringParameterSasunicode = false
postScript:
デフォルトでは、Javaの文字データはUnicodeとして処理されます。 Java文字列オブジェクトは、Unicode文字データを表します。 JDBCドライバーでは、このルールに従わない唯一のことは、ASCIIストリームゲッターとセッターメソッドのみです。これらのメソッドで使用されるバイトストリームは、単一の既知のコードページ(ASCII)の暗黙的な仮定を伴うためです。
さらに、JDBCドライバーは、sendStringParameterSasunicode接続文字列プロパティを提供します。このプロパティを使用して、Unicodeの代わりにASCIIとして送信された文字データの事前定義されたパラメーターを指定できます。
パフォーマンスの強化として、sendStringParameterSasunicode接続文字列プロパティを設定することにより、文字列パラメーターを非ユニコード形式でSQL Serverに渡すことができます。 SendStringParameterSasunicodeのデフォルト設定は「True」です。つまり、文字列パラメーターはUnicodeとして送信されます。
SendStringParameterSasunicodeが「false」に設定されている場合、接続上のすべての文字列パラメーターは、データベースのデフォルト照合を使用してサーバーに送信されます。
参照:
http://d.hatena.ne.jp/gnarl/20110706/1309945379
https://technet.microsoft.com/zh-cn/library/ms378857(sql.90).aspx
https://technet.microsoft.com/zh-cn/library/ms378988(v=sql.90).aspx