I need to count the number of rows from different(!) tables and save the results for some kind of statistic. The script is quite simple and working as expected, but I'm wondering if it's better to use a single query with (in this case) 8 subqueries, or if I should use separate 8 queries or if there's even a better, faster and more advanced solution...
I'm using MySQLi with prepared statements, so the single query could look like this:
$sql = 'SELECT
(SELECT COUNT(cat1_id) FROM `cat1`),
(SELECT COUNT(cat2_id) FROM `cat2`),
(SELECT COUNT(cat2_id) FROM `cat2` WHERE `date` >= DATE(NOW())),
(SELECT COUNT(cat3_id) FROM `cat3`),
(SELECT COUNT(cat4_id) FROM `cat4`),
(SELECT COUNT(cat5_id) FROM `cat5`),
(SELECT COUNT(cat6_id) FROM `cat6`),
(SELECT COUNT(cat7_id) FROM `cat7`)';
$stmt = $db->prepare($sql);
$stmt->execute();
$stmt->bind_result($var1, $var2, $var3, $var4, $var5, $var6, $var7, $var8);
$stmt->fetch();
$stmt->free_result();
$stmt->close();
while the seperate queries would look like this (x 8):
$sql = 'SELECT
COUNT(cat1_id)
FROM
`cat1`';
$stmt = $db->prepare($sql);
$stmt->execute();
$stmt->bind_result($var1);
$stmt->fetch();
$stmt->free_result();
$stmt->close();
so, which would be faster or "better style" related to this kind of query (e.g. statistics, counter..)
Just to follow up your comment, here is an example using one of my DBs. Using a prepared statement here buys you nothing. This multiple query in fact only executes one RPC to the D/B engine. All of the other calls are local to the PHP runtime system.
Just out of interest, I did an
strace
on this and the relevant four lines areThere was ~1 mSec between the query and the response to and from the MySQLd process (this is because this was on localhost, and the results were in its query cache, BTW).. and 0.8 mSec later the DB close was executed. And that's on my 4-yr old laptop.
Regarding to TerryE's example and the advice to use multi_query(!), I checked the manual and changed the script to fit my needs.. finally I got a solution that looks like this:
There are some differences to TerryE's example, but the result is the same. I'm aware that there are 7 line at the beginning that are almost identical, but as soon as I need a WHERE clause or something else, I prefer this solution to a foreach loop where I'd need to add queries manually or use exceptions with
if { ... }
...As far as I can see, there should be no problem with my solution, or did I miss something?
My inclination is to put queries into the FROM rather than the SELECT, where possible. In this example, it requires a cross join between the tables:
The performance should be the same. However, the advantage appears with your cat2 table:
You get a real savings here by not having to scan the table twice to get two values. This also helps when you realize that you might want to modify queries to return more than one value.
I believe the cross join and select-within-select would have the same performance characteristics. The only way to really be sure is to test different versions.
The better way, is use just one query, because is only one conecction with database, instead of, if you use many queries, then are many conecctions with database, this process involves: coneccting and disconeccting, and this is more slower.