问题
We noticed that a call to our API endpoint usually have multiple duplicated MySQL queries for SELECT
statements (sometimes hundreds). So we decided to create a hashmap to store the
mysqli_result
and check if a given query has already been done and return the result saved in our map.
My question is: do mysqli_result
maintain a reference to our connection? Would this actually help us to avoid overloading our database with queries that have already been requested unnecessarily? If the mysqli_result
is too big, could this overflow the memory for our fpm
process?
What I want to know basically is what approach is better:
- For query A, reuse
mysqli_result
object everytime I need it; - Redo query A everytime I need it.
回答1:
mysqli_result()
requires neither a connection to MySQL nor a mysqli
object once the results are fetched from MySQL.
Caveat: The above only applies to the buffered queries. If you are using unbuffered resultsets then mysqli_result
requires an open mysqli connection to fetch the data otherwise you will receive an error saying:
PHP Warning: mysqli_result::fetch_all(): Error while reading a row in ...
However, this error message can only happen when you close the connection when using unbuffered queries. e.g.
$res = $mysqli->query('SELECT id FROM Users LIMIT 1', MYSQLI_USE_RESULT);
$mysqli->close();
$res->fetch_all();
Even though mysqli_result
requires a valid connection when creating an instance of it, it only needs the connection to fetch the data. The second parameter in the mysqli_result::__construct()
is used to decide whether the resultset should be buffered in PHP or stored on MySQL server and fetched row by row. When you create an instance of mysqli_result
you need to pass an instance of mysqli
as the first parameter.
// Execute query on MySQL server
$res = $mysqli->real_query('SELECT id FROM Users LIMIT 1');
// Create the result object.
// The second argument can be MYSQLI_STORE_RESULT for buffered result or MYSQLI_USE_RESULT for unbuffered.
$res = new mysqli_result($mysqli, MYSQLI_STORE_RESULT);
// If MYSQLI_STORE_RESULT was used then you can close mysqli here.
unset($mysqli); // or $mysqli->close(); or both
$data = $res->fetch_all();
// If MYSQLI_USE_RESULT was used then you can't close mysqli yet.
// unset($mysqli);
$data = $res->fetch_all();
Buffering of SQL queries is a rather complex task and it would be better to avoid duplicate calls rather than implementing caching. Try to refactor your code so that it does not call the same SELECT
query multiple times during the execution of your script.
There is also a pre-made solution for this, although not very popular. Mysqlnd query result cache plugin
And as always remember that:
premature optimization is the root of all evil
来源:https://stackoverflow.com/questions/62745018/do-mysqli-result-need-an-alive-connection-to-seek-results