I have the following query which is used to make graphs for my users. The only problem is sometimes this can overload the server and I can get hanging queries.
I noticed this answer from goat which allows asnchonous mysqli connections, which uses a basic query methodology:
How to set a maximum execution time for a mysql query?
However, I want to be able to use prepared statements for security reasons. And the documentation for asynchronous queries is very limited.
How can I integrate asynchronous mysqli using prepared statements that will return as many rows as it can, within an execution time limit?
$query = "
SELECT
t1.day AS day,
COALESCE(t1.amount,0) AS earnings,
COALESCE(t2.amount,0) AS publisher_referral_earnings,
COALESCE(t3.amount,0) AS advertiser_referral_earnings
FROM
(
SELECT DATE_FORMAT(earning_created, '%c/%e/%Y') AS day, SUM(earning_amount) AS amount
FROM earnings
WHERE earning_referral_id = 0
AND (earning_created > DATE_SUB(now(), INTERVAL 30 DAY))
AND earning_account_id = ?
GROUP BY DATE(earning_created)
) t1
LEFT JOIN
(
SELECT DATE_FORMAT(ep.earning_created, '%c/%e/%Y') AS day, (SUM(ep.earning_amount) * rp.referral_share) AS amount
FROM earnings AS ep
INNER JOIN referrals AS rp
ON ep.earning_referral_id = rp.referral_id
WHERE ep.earning_referral_id > 0
AND (ep.earning_created > DATE_SUB(now(), INTERVAL 30 DAY))
AND ep.earning_account_id = ?
AND rp.referral_type = 0
GROUP BY DATE(ep.earning_created)
) t2
ON t1.day = t2.day
LEFT JOIN
(
SELECT DATE_FORMAT(ea.earning_created, '%c/%e/%Y') AS day, (SUM(ea.earning_amount) * ra.referral_share) AS amount
FROM earnings AS ea
INNER JOIN referrals AS ra
ON ea.earning_referral_id = ra.referral_id
WHERE ea.earning_referral_id > 0
AND (ea.earning_created > DATE_SUB(now(), INTERVAL 30 DAY))
AND ea.earning_account_id = ?
AND ra.referral_type = 1
GROUP BY DATE(ea.earning_created)
) t3
ON t1.day = t3.day
";
And here's the mysqli:
if ($statement = $mysqli->prepare($query))
{
$statement->bind_param("iii", $account_id, $account_id, $account_id);
$statement->execute();
$statement->store_result();
$timescales_total = $statement->num_rows;
$statement->bind_result($timescale, $earnings, $publisher, $advertiser);
$statement->free_result();
$statement->close();
}