16ms〜30msで実行される次のクエリがあります。ハッシュを含むインデックス付き列を検索するcfqueryparamによるクエリが遅い
<cfquery name="local.test1" datasource="imagecdn">
SELECT hash FROM jobs WHERE hash in(
'EBDA95630915EB80709C69089315399B',
'3617B8E6CF0C62ECBD3C48DDF8585466',
'D519A38F09FDA868A2FEF1C55C9FEE76',
'135F94C3774F7719CFF8FF3A275D2D05',
'D58FAE69C559273D8427673A08193789',
'2BD7276F209768F2FCA6635659D7922A',
'B1E3CFBFCCFF6F5B48A849A050E6D424',
'2288F5B8A797F5302E8CA24323617236',
'8951883E36B5D38A4643DFAA0396BF13',
'839210BD564E30BE1355D1A6D4EF7081',
'ED4A2CB0C28B608C29576819CF7BE19B',
'CB26925A4874945B810707D5FF0B91F2',
'33B2FC229F0CC797A02AD163CDBA0875',
'624986E7547DBAC0F47B3005CFDE0A16',
'6F692C289BD805CEE41EF59F83F16F4D',
'8551F0033C617BD9EADAAD6CEC4B3E9E',
'94C3C0A74C2DE085FF9F1BBF928821A4',
'28DC1A9D2A69C2EDF5E6C0E6368A0B3C'
)
</cfquery>
私は同じクエリを実行しますがでcfqueryparamを使用する場合は、500ミリ秒で実行されます - 2000ミリ秒。
<cfset local.hashes = "[list of the same ids as above]">
<cfquery name="local.test2" datasource="imagecdn">
SELECT hash FROM jobs WHERE hash in(
<cfqueryparam cfsqltype="cf_sql_varchar" value="#local.hashes#" list="yes">
)
</cfquery>
テーブルは、およそ60,000行を有します。 「ハッシュ」列はvarchar(50)で、クラスタ化されていない一意のインデックスを持ちますが、プライマリキーではありません。 DBサーバーはMSSQL 2008です。Webサーバーは最新バージョンのCF9を実行しています。
なぜcfqueryparamがパフォーマンスを爆発させるのでしょうか?ページをリフレッシュした回数に関係なく、毎回このように動作します。リストを2〜3ハッシュだけにペアリングしても、それは150〜200msのようにうまく動作しません。 cfqueryparamを削除すると、パフォーマンスは期待どおりです。このような状況では、SQLインジェクションの可能性があるため、cfqueryparamを使用するのが望ましいでしょうが、インデックス付きの列から2レコードを見つけるのに100msかかるべきではありません。
編集:
我々は
hash()
ないのUUIDまたはGUIDSによって生成されたハッシュを使用しています。ハッシュはhash(SerializeJSON({ struct }))
によって生成され、画像に実行する一連の操作の計画が含まれています。これは、その構造の正確な一意のIDを挿入前と照会前に知ることができるということです。これらのハッシュは、どの構造体が既にDBに格納されているかの「インデックス」として機能します。さらに、ハッシュで同じ構造体が同じ結果にハッシュされますが、これはUUIDSとGUIDSでは当てはまりません。クエリは5つの異なるCF9サーバーで実行されており、すべて同じ動作を示します。私にとって、これはCF9が何かをキャッシュしているという考えを排除します。すべてのサーバーがまったく同じDBに接続しているので、キャッシュが発生している場合はDBレベルにする必要があります。
varcharの代わりにcf_sql_charを使用してみましたか? MSSQLが配列を詳しく観察し、より良い実行計画を出すようにするかもしれません。明らかに、キャッシュから来る計画は、リアルタイムでコンパイルする計画ほど効率的ではありません。また、インデックスヒントを追加してみてください。開発システムでトレースアナライザを実行すると、トレースアナライザが実行され、実行計画にいくつかの手がかりが与えられます。それは私が持っているものです:) –
リストのprepare文を再利用することができないため、毎回再コンパイルしている可能性があります。独自のロジックを使用してSQLインジェクションを防ぐことができたら、cfqueryparamこのため。 – Henry
ここではSELECT INのパフォーマンスを向上させるためのいくつかの方法があります。http://florianreischl.blogspot.ca/2012/03/performance-comparison-of-sql-server.html – Henry