2017-02-22 10 views
1

バインディングパラメータを使用している場合にのみ、特定のクエリで奇妙なパフォーマンスの問題が発生します。ここでバインドパラメータのMySQLパフォーマンスの問題

は私のコードです:

$statement = $connection->prepare('SELECT count(item_id) AS count FROM MyView WHERE active = 1 AND context_id = 5 AND snapshot_id = 24'); 
$time_start = microtime_float(); 
$statement->execute(); 
$time_end = microtime_float(); 
$time1 = round($time_end - $time_start, 4); 
$result = $statement->fetch()['count']; 

$statement = $connection->prepare('SELECT count(item_id) AS count FROM MyView WHERE active = :filter_active AND context_id = :filter_context_id AND snapshot_id = :filter_snapshot_id'); 
$statement->bindValue('filter_active', 1, 2); 
$statement->bindValue('filter_context_id', 5, 2); 
$statement->bindValue('filter_snapshot_id', 24, 2); 
$time_start = microtime_float(); 
$statement->execute(); 
$time_end = microtime_float(); 
$time2 = round($time_end - $time_start, 4); 
$result = $statement->fetch()['count']; 
enter code here 

時間の結果:私たちは、この巨大なパフォーマンスの差を取得する理由

time1 = 0.79 sec 
time2 = 31.50 sec 

は、誰かが私に説明してもらえますか?

おかげ

EDIT &ソリューション: パラメータの型が間違っていました。代わりにPDO :: PARAM_INTを使用してください。 私がparam型を指定しないと、パフォーマンスが非常に悪いことに注意してください。

+4

a)microtime_float()は正確に何を行い、マイクロタイム(true)とどのように違うのですか? b) 'PDO :: PARAM_STR = 2'、' PDO :: PARAM_INT = 1' - なぜ整数値を文字列としてバインドするのですか? c)テーブル構造はどのように見えるのですか、その中にどのくらいのデータがあり、どのindizesを使用していますか? –

+1

文字列としてのバインディングは、私が最初にこの問題について推測するものです。 – Kickstart

+0

ありがとうございました!それは間違っていたバインディングタイプです。 PDO :: PARAM_INTを使用すると0.0005秒の実行時間が得られます! –

答えて

0

ああ、いくつかの質問に間違っているコメント!

  • SHOW CREATE TABLEを指定してください - データ型、インデックス、およびエンジン(少なくとも)を確認する必要があります。
  • 速い実行のために、(active, context_id, snapshot_id)のインデックスを任意の順序で使用してください。
  • count(item_id)の代わりに、たとえばcount(*)としてください。前者は、NULLでないためにitem_idをテストする必要があるときです。
  • WHERE int_col = 123およびWHERE int_col = "123"は、性能が事実上同一であり、実質的に同一である。悪い組み合わせはWHERE char_col = 123です - この場合、比較する前に各char_colを数値に変換します。これは索引付けを役に立たなくします。
  • 0.0005 secは非常に偽である可能性があります。おそらく、クエリキャッシュがオンになっているかもしれません。つまり、クエリが最近実行され、QCにキャッシュされてから再度実行されたときに起こるような小さな時間です。クエリを再実行するのではなく、単にQCから結果セットを取り出すだけです。
  • 「正直な」タイミングでは、QCを避けるためにSELECT SQL_NO_CACHE ...を使用してください。その後、I/Oキャッシングを避けるために2回実行します(2回目のタイミングを取る)。
+0

あなたのフィードバックのために、ありがとうございます。 –

+0

問題はリクエスト自体ではなく、PHPを通して実行される方法です。同じ要求、2回の実行時間は非常に異なります。コメントが私の問題を解決しました。 とにかく、 非常に複雑なので、テーブル構造を表示できません。 2 - 私は経験したインデックスは、パフォーマンスの違いを変更しませんでした。そして、列の順序はインデックスで非常に重要です。 3 - 興味深いコメント 4 - おそらく 5 - 次回このSQL_NO_CACHEオプションを使用します。 ありがとう –

+0

'VIEWs'は物事を複雑にします - 時には同等の' SELECT'がより速く実行されます。Bindingは数字の周りに引用符を入れますが、あなたが経験している実行時間には影響しません。 –

関連する問題