MySQL queries in PHP - php

Two quick (I hope!) questions:
Counting rows
Is it more efficient to use COUNT(id) in an SQL query, or to just select all the rows and use PHP's mysql_num_rows() function on the returned resource? Would this depend on the size of the results query? Is there a fairly easy way of determining the answer to this question?
Results arrays
At the moment, I am using COUNT(id) in a query, and then obviously using mysql_query() and mysql_fetch_array(), as follows:
$sql = "SELECT COUNT(id) FROM TABLE1;";
$resource = mysql_query($sql) or die(mysql_error())
$result = mysql_fetch_array($resource);
$count = $result[0];
and this returns the number of rows fine. However, I'm surprised that
$count = mysql_fetch_array($resource)[0];
doesn't work; I get the error:
Parse error: syntax error, unexpected '[' in C:\ServerDocs\file1.php on line 44
is there an easy explanation as to what's going on?
Thanks in advance,
Chris

It depends on the situation, but SELECT COUNT(*) is normally faster.
The reason is simply that using mysql_num_rows(), the database
server has to actually build the result set. With a COUNT(*), on the
other hand, the DB may be able to determine the number of rows just
from indexes, which is much faster. So if all you want is the count,
then mysql_num_rows() ends up doing a lot more work for the same
result.
Another down side is that mysql_num_rows doesn't work with
unbuffered queries. So if you need to work with very large result
sets, using mysql_num_rows might not be an option. However, COUNT(*)
is always available.
$count = mysql_fetch_array($resource)[0];
This type of statements are not possible in current version of php.
So, better use
$no_of_rows = mysql_fetch_array($count);
echo $no_of_rows[0];

1) mysql_query gets all the results and the you do a count on the results. Therefore performance is related to the number of results. If you do count(*) it is a DB select which results only one row/column. In this case database does everything for you, which is usually considered better.
2) $count = mysql_fetch_array($count)[0]; is not possible. Do the following:
$count = mysql_fetch_array($count);
echo $count[0];

Related

PDO unbuffered query still waits until query result is complete

I have an SQL query which can return quite a lot results (something like 10k rows) but I cannot use the SQL LIMIT parameter, as I don't know the exact amount of needed rows (there's a special grouping done in PHP). So the plan was to stop fetching rows once I have enough.
Since PDO normally operates in buffered mode, which fetches the whole result set and passes it to PHP, I switched PDO to unbuffered mode with
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
Now I expected that executing the query should take about the same time no matter what LIMIT I pass. So basically
$result = $pdo->query($query);
$count = 0;
while ($row = $result->fetch()) {
++$count;
if ($count > 10) break;
}
should execute in about the same time for
$query = 'SELECT * FROM myTable';
and
$query = 'SELECT * FROM myTable LIMIT 10';
However the first one takes 8 seconds whereas the second one executes instantly. So it seems like the unbuffered query also waits until the whole result set is fetched - which shouldn't be the case according to the documentation.
Is there any way to get the query result instantly in PHP with PDO and stop the query once I have enough results?
Database applications like "Sequel Pro SQL" can do this (I can hit cancel after 1 second and get the results that were already queried until that time) so it can't be a general problem with MySQL servers.
I can workaround the problem by choosing a very high LIMIT which always has enough valid results after my grouping. But since performance is an issue, I'd like to query only as many entries as really needed. Please don't suggest anything that involves grouping in MySQL, the terrible performance of that is the reason we have to change the behaviour.
Now I expected that executing the query should take about the same time no matter what LIMIT I pass. So basically
This might not be completely true. While you won't get the overhead of receiving all your results, they are all queried (without a limit)! You do get the advantage of keeping most of the results serverside until you need them, but your server actually does perform the whole query first as far as I know. I'm not sure how complicated your query is, but this could be the issue?
Say for instance you have a very slow join (not indexed), but only want the first 10 by id, your query will get 10 based on the index, and then only do the join for those 10. This'll be quick
But if you don't actually limit, but ask for the result in batches, your complete join will have to be done (slow!) and then your resultsset is released in parts.
A quicker method might be to repeat your limited query untill you have your result. I know, this will increase overhead, but it might be way quicker. Only way to know is to test.
as response to your comment: this is from the manual
Unbuffered MySQL queries execute the query and then return a resource while the data is still waiting on the MySQL server for being fetched.
So it executes the query. The complete query. So as I tried to explain above, it will not be as quick as the same query with a LIMIT 10, as it doesn't perform a partial query! The fact that a different DB engine does this does not mean MySQL can...
Have you tried using prepare/execute instead of query, and putting a $stmt->closeCursor(); call after the break?
$stmt = $dbh->prepare($query);
$stmt->execute();
$count = 0;
while ($row = $stmt->fetch()) {
++$count;
if ($count > 10) break;
}
$stmt->closeCursor();

SQL LIMIT VS Loop Limit

I was browsing around Stack Overflow attempting to find how to limit an SQL query with a while loop and I came across this code.
$count = 0;
while ($count < 4 && $info = mysql_fetch_assoc($result)) {
//stuff
$count++;
}
Q 1: What is the difference between this code and using the SQL LIMIT clause?
Q 2: For what reason would somebody want to use this code, rather than using LIMIT?
With this code, the MySQL server will send all the results to the client, but the client ignores everything after the 4th row. So the server has to do more work, and more bandwidth will be used between the client and server.
They might want to use mysql_num_rows() to find out how many total rows were selected, even though they only want to display the first 4. However, MySQL provides a way to do that with LIMIT -- you can put the SQL_CALC_FOUND_ROWS option in the SELECT clause, and then use SELECT FOUND_ROWS() to get the total number of rows. So there's no good reason, except they don't know about this feature.
Everyting #Barmar said is right on. Following with code like that will cause lots of problems as your result sets start to grow. Let a database do what its good at doing, let it supply the limit of results you want/need. Just think of what happens when you do a SELECT with no LIMIT clause in the command line client where there are thousands of rows...it just goes on and on.
One more thing, I wouldn't recommend using mysql_num_rows() as its a deprecated function. Might as well go along with mysqli or PDO.

PHP or MYSQL not recognizing value

I'm using php to query from mysql in which either the home_team or away_team column contains a given value. I know that records of such values exist in the DB. But, for some reason either PHP or MySQL is telling me that it's not. My code is as follows.
$teams = array("St. Louis",
"NY Yankees",
"NY Mets",
"LA Dodgers",
"LA Angels");
foreach($teams as $given_team)
{
$query = mysql_query("SELECT COUNT(*) FROM current_season_games WHERE home_team = '".$given_team."' OR away_team = '".$given_team."'")or die(mysql_error());
$count = mysql_result($query, 0);
echo "".$count."<br />";
}
I know that the $count variable that's being echoed is incorrect. I'm looking at some rows in the DB that fit the conditions specified in the query.
Any ideas?
Thanks,
Lance
You are using COUNT(*). This won't give you the value of the field. COUNT(*) is usually used to measure how many results are returned.
What you'll want to do is actually select the column name or alternatively, select the entire row that matches the criteria. Something like this -
SELECT * FROM current_season_games
WHERE home_team = '".$given_team."' OR away_team = '".$given_team."'")
Here are a couple of things to check:
is PHP connecting to the same host and database? (This has been a 'DOH!' moment for some developers, when they have multiple databases... one local, and one on a test server.) Are you sure you are querying the same table?
try testing a simpler query, e.g. SELECT COUNT(*) FROM current_season_games to see if you can get any non-zero count returned
try putting the query into a string, and echoing out the string, before you execute it
is this an InnoDB table, and have the rows you are trying to count been committed? (Did the session adding the rows do a START TRANSACTION, insert the rows, and then not yet commit them? (This is a DOH! moment for some developers that are using multiple environments (e.g. SQLyog and a web server). (A separate session with transaction isolation level of REPEATABLE READ would not see the uncommitted rows)
is that column in the database using a case sensitive collation, where the equality comparison in the predicates (WHERE clause) is being handled as case sensitive vs. case insensitive?
None of those may solve your problem, but it's impossible to tell (from here), without a lot more information, what the issue is. But it's a few things you can check.
In old code that I come across still using the deprecated mysql_* functions, I'll usually come across the use of the mysql_num_rows() function.
Retrieves the number of rows from a result set. This command is only valid for statements like SELECT or SHOW that return an actual result set. To retrieve the number of rows affected by a INSERT, UPDATE, REPLACE or DELETE query, use mysql_affected_rows().
I would recommend changing your code to something like this -
$result = mysql_query("SELECT COUNT(*) FROM current_season_games WHERE home_team = '".$given_team."' OR away_team = '".$given_team."'")or die(mysql_error());
$count = mysql_num_rows($result);
Notice that the mysql_query() function doesn't return a $query as your variable name indicates. It returns a result set that you can then inspect to retrieve that actual data.

For SQL row count, is it more efficient to use PDO rowCount or count(*) AS?

On my script, I have about 15 SQL queries just for counting the number of rows and displaying them to the user.
What is the most efficient way?
Should I use:
$stmt=$cxn->prepare("SELECT id FROM items WHERE seller=?");
$stmt->execute(array($username));
echo $stmt->rowCount();
Or this:
$stmt=$cxn->prepare("SELECT count(*) as count FROM items WHERE seller=?");
$stmt->execute(array($username));
while($row=$stmt->fetch(PDO::FETCH_ASSOC))
echo $row['count'];
Thanks in advance.
The short answer is Count(*) will be faster.
However, that assumes your not using the data, if you are going to select the data, and you want a count, then use your first method.
("SELECT id FROM items WHERE seller=?");
If you have an index on the table, then that will return almost instantly.
The rowCount command can be used not only for SELECT queries but also for UPDATE,INSERT etc.
So that's a benefit for that.
However according to the PDO documentation :
not guaranteed for all databases and should not be relied on for portable applications.
So in your case i'd suggest using count without worrying about preformence, though it will slightly faster.
It will be faster to use the MySQL row count. Less bandwidth is needed between PHP and the database.

How to get number of returned rows from a database

After I perform a database query, and some rows are echoed, it seems that I can't get the number of rows which are shown, after the query. Tried to use mysql_num_rows() but my $result is like this:
$result = $conn->query($sql) or die();
so I think that the problem is that I've used the built-in MySQLi() class, and for some reason
mysql_num_rows() is not working in accordance with this $result. How can I get it to work with the current $result I'm using, or is there any other way to return the number of rows using the MySQLi() class to create the $result??
mysql and mysqli are NOT interchangeable. They're two completely different modules, maintain their own separate connections, and are results/handles from one are NOT useable in the other. They may both use the same underlying mysql libraries and talk to the same database, but they're utterly independent of each other.
If you're using MySQLi, then stick with MySQLi functions, which for your problem would be to use http://php.net/manual/en/mysqli-stmt.num-rows.php
Note1: If you only need the number of rows in your table, it is better to do the folowing:
$result = $conn->query("SELECT COUNT(*) FROM `table`");
$row = $result->fetch_row();
echo '#: ', $row[0];
Note 2: Don't mix up mysqli_field_count and mysqli_stmt_num_rows. For example :
id firstname
1 foo
2 bar
3 baz
field_count is 2
num_rows is 3

Categories