推奨されるソリューション
まず、found_rows()関数は移植性がなく(MySQL拡張機能です)、削除されます。ユーザー@Zveddochkaが指摘したように、MySQL8.0.17ではすでに非推奨になっています。
しかし、もっと重要なことは、適切なインデックスを使用すると、2つのクエリを実行する方が実際には高速であることがわかります。このSQL_CALC_FOUND_ROWS
ディレクティブは、追加のリカバリコストが発生する「仮想スキャン」によって実現されます。クエリにインデックスが付けられていない場合、このコストはと同じにCOUNT()
なります。したがって、2つのクエリを実行すると、コストが2倍になります。つまり、を使用SQL_CALC_FOUND_ROWS
すると、実行速度が50%速くなります。
しかし、クエリが適切にインデックス付けされるとどうなりますか?Perconaの人たちはそれをチェックしました。また、COUNT()
メタデータとインデックスにのみアクセスするため、が高速であるだけでSQL_CALC_FOUND_ROWS
なく、追加コストが発生しないため、なしのクエリが高速であることがわかります。2つのクエリを組み合わせたコストは、拡張された単一のクエリのコストよりも低くなります。
SQL_CALC_FOUND_ROWSの結果は次のとおりです。各b値について、キャッシュされていない実行には20〜100秒、ウォームアップ後は2〜5秒かかります。このような違いは、このクエリに必要なI / Oによって説明できます。mysqlは、LIMIT句なしでこのクエリが生成できるすべての10k行にアクセスします。
The results are following: it takes 0.01-0.11 sec to run this query
first time and 0.00-0.02 sec for all consecutive runs.
So, as we can see, total time for SELECT+COUNT (0.00-0.15 sec) is much
less than execution time for original query (2-100 sec). Let’s take a
look at EXPLAINs...
So, what to do?
// Run two queries ensuring they satisfy exactly the same conditions
$field1 = "Field1, Field2, blah blah blah";
$field2 = "COUNT(*) AS rows";
$where = "Field5 = 'X' AND Field6 = 'Y' AND blah blah";
$cntQuery = "SELECT {$field2} FROM {$joins} WHERE {$where}";
$rowQuery = "SELECT {$field1} FROM {$joins} WHERE {$where} LIMIT {$limit}";
Now the first query returns the count, the second query returns the actual data.
Old answer (useful just for non-indexed tables)
Don't do this. If you find out this section of the answer works for you better than the section above, it's almost certainly a signal that something else is not optimal in your setup - most likely you're not using the indexes properly, or you need to update your MySQL server, or run an analyze/optimize of the database to update cardinality statistics.
できますが、パフォーマンスのキラーになると思います。
最善のオプションは、SQL_CALC_FOUND_ROWS
MySQL拡張機能を使用し、2番目のクエリを発行してFOUND_ROWS()を使用して行の全数を回復することです。
SELECT SQL_CALC_FOUND_ROWS * FROM t WHERE t.nid <1000 LIMIT 10;
SELECT FOUND_ROWS();
たとえば、http ://www.arraystudio.com/as-workshop/mysql-get-total-number-of-rows-when-using-limit.htmlを参照してください。
LIMIT
または、句なしで完全なクエリを実行し、最初の10行のみを取得することもできます。次に、必要に応じて1つのクエリを使用し、を介して行数を取得することもできますmysql_num_rows()
。これは理想的ではありませんが、ほとんどのクエリにとってそれほど壊滅的ではありません。
ただし、これを最後に行う場合は、クエリを閉じてそのリソースを解放するように十分注意してください。完全な結果セットよりも少ない値を取得し、rsハンドルを解放するのを忘れることが、「メタデータロック」の顕著な原因の1つであることがわかりました。