I get my array of data via MySQL PDO:
"select * from table"
Is it faster to order using function within query such as
"select * from table order by key"
Do I sacrifice a lot of efficiency by using a PHP usort or any other array sort compared to a straight mysql order query?
$prepare=$database->prepare("select * from table");
$prepare->execute();
$fetch=$prepare->fetchall(PDO::FETCH_ASSOC);
usort($fetch, ...)
In general mysql order works very fast and it handy to use it, but it's correct in case where you have indexes and you use that index in query for ordering data and explain of that query is good, but in some cases php sorts works really faster (i have situation where my query selects huge batch of records that group it and than having it and than order a small result by field without index).
There is no one rule for this, you should benchmark both approaches.
The problem here is with your toy example. In reality you never run a query like "select * from table". While with real live queries you never select the whole table, but just several records. So there will be just no way to sort records in PHP, and you will have to stick with sorting on mysql side, for which purpose a database were invented.
Related
I am working on converting a prototype web application into something that can be deployed. There are some locations where the prototype has queries that select all the fields from a table although only one field is needed or the query is just being used for checking the existence of the record. Most of the cases are single row queries.
I'm considering changing these queries to queries that only get what is really relevant, i.e.:
select * from users_table where <some condition>
vs
select name from users_table where <some condition>
I have a few questions:
Is this a worthy optimization in general?
In which kind of queries might this change be particularly good? For example, would this improve queries where joins are involved?
Besides the SQL impact, would this change be good at the PHP level? For example, the returned array will be smaller (a single column vs multiple columns with data).
Thanks for your comments.
If I were to answer all of your three questions in a single word, I would definitely say YES.
You probably wanted more than just "Yes"...
SELECT * is "bad practice": If you read the results into a PHP non-associative array; then add a column; now the array subscripts are possibly changed.
If the WHERE is complex enough, or you have GROUP BY or ORDER BY, and the optimizer decides to build a tmp table, then * may lead to several inefficiencies: having to use MyISAM instead of MEMORY; the tmp table will be bulkier; etc.
EXISTS SELECT * FROM ... comes back with 0 or 1 -- even simpler.
You may be able to combine EXISTS (or a suitable equivalent JOIN) to other queries, thereby avoiding an extra roundtrip to the server.
I need to migrate a code from .NET to MySQL and looking for an analog to the recordset SORT function. In my .NET code it was easy to create a recordset and run multiple sort operation across different fields. It was extremely fast even for large recordsets of over half a million records.
I understand that in MySQL I can use an ORDER BY clause, but in that case I will need to run multiple db queries, which is not a good solution from the performance point.
How can I sort a query result on different fields without executing multiple queries? PHP array sort functions or there are some better options?
Thanks!
ORDER BY works on multiple fields. Is that what you mean?
SELECT [column list] FROM table
ORDER BY field1, field2
If is posible, how can I fetch two results sets:
$sth=$dbh->prepare("SELECT * FROM tb1 WHERE cond1;
SELECT * from tb2 Where cond2");
$sth->execute();
$row=$sth->fetchAll(); print_r ($row);
These are two completely different tables (no fiels in common).
Yes PDO can fetch two (or more) rowsets, as long as the database you are using supports it. I think MS SQL Server and MySQL both support this functionality, but at the time of writing SQLite does not.
The function you want is PDOStatement::nextRowset
So in your example above, you might do something like;
$sth = $dbh->prepare("SELECT * FROM tb1 WHERE cond1;
SELECT * FROM tb2 WHERE cond2");
$sth->execute();
$rowset1 = $sth->fetchAll();
$sth->nextRowset();
$rowset2 = $sth->fetchAll();
print_r($rowset1);
print_r($rowset2);
It's perfectly reasonable for a single stored procedure to return more than one rowset.
$rowset[] = $sth->fetchAll(PDO::FETCH_OBJ);
WHILE($sth->nextRowset()) {
$rowset[] = $sth->fetchAll(PDO::FETCH_OBJ);
}
Now your $rowset will be an array. You may use count() to find out how many rowsets you have. And use foreach loop to get each rowset
Depending on the specific version of PHP you're using, you might not even be able to execute multiple statements per query / execute.
The short answer is that no, it is not better to return two separate tables in one query. Both tables would have to have the same amount of columns. There won't be a way of telling result #1 from result #2 in PHP. And if you ever want to change either of the tables, you'll have to ensure that the tables still remain compatible.
You might be able to write a benchmark which runs a couple of thousand queries, first as two separate ones, and then one as UNION ALL (as suggested above). I doubt you're going to find much of a performance difference between the two. If the SQL server is running on the same physical server, the query itself is near instantaneous and you may incur a performance hit for doing the UNION ALL. If it is over the wire, to another server on the network, or over the internet (for whatever reason) that will offset the benefit of the combined query.
If these are semantically separate pieces information, it just isn't a very good idea in the long run to tie the two queries together. This smacks of "premature optimization", and that is the root of all evil as Donald Knuth says.
$STH = $DBH->prepare('show create table `a`;
show create table `b`;
show create table `b`;
');
$STH->execute( );
do {
$row =$STH->fetchAll(\PDO::FETCH_NUM);
if($row && count($row)>0){
$sql.=$row[0][1] . ';';
}
} while ($STH->nextRowset());
A multi result set in one loop
To answer your question, no, it's not possible how you are doing it. You have two options:
Combine both queries into one
Execute both queries separately and combine their results
Since mysql queries tend to be expensive, I would combine the queries if at all possible. In your case you could use a simple UNION:
SELECT row1, row2, row3
FROM tb1
WHERE id < 10
UNION ALL
SELECT row1, row2, row3
FROM tb2
WHERE id < 10
However you should probably evaluate why you are using two separate tables. If they contain overlapping data, it may be better to combine into one table, if possible.
Perhaps you need JOIN if these tables are connected.
Or 2 separate calls if it's completely different and irrelevant tables.
It's impossible to tell more because of your extremely short and obscure question.
Anyway, there is no reason to combine queries only out of desire to run them all in one trip.
consider "Query1", which is quite time consuming. "Query1" is not static, it depends on $language_id parameter, thats why I can not save it on the server.
I would like to query this "Query1" with another query statement. I expect, that this should be fast. I see perhaps 2 ways
$result = mysql_query('SELECT * FROM raw_data_tbl WHERE ((ID=$language_id) AND (age>13))');
then what? here I want to take result and requery it with something like:
$result2 = mysql_query('SELECT * FROM $result WHERE (Salary>1000)');
Is it possible to create something like "on variable based" MYSQL query directly on the server side and pass somehow variable $language_id to it? The second query would query that query :-)
Thanks...
No, there is no such thing as your second idea.
For the first idea, though, I would go with a single query :
select *
from raw_data
where id = $language_id
and age > 13
and Salary > 1000
Provided you have set the right indexes on your table, this query should be pretty fast.
Here, considering the where clause of that query, I would at least go with an index on these three columns :
id
age
Salary
This should speed things up quite a bit.
For more informations on indexes, and optimization of queries, take a look at :
Chapter 7. Optimization
7.3.1. How MySQL Uses Indexes
12.1.11. CREATE INDEX Syntax
With the use of sub queries you can take advantage of MySQL's caching facilities.
SELECT * FROM raw_data_tbl WHERE (ID='eng') AND (age>13);
... and after this:
SELECT * FROM (SELECT * FROM raw_data_tbl WHERE (ID='eng') AND (age>13)) WHERE salary > 1000;
But this is only beneficial in some very rare circumstances.
With the right indexes your query will run fast enough without the need of trickery. In your case:
CREATE INDEX filter1 ON raw_data_tbl (ID, age, salary);
Although the best solution would be to just add conditions from your second query to the first one, you can use temporary tables to store temporary results. But it would still be better if you put that in a single query.
You could also use subqueries, like SELECT * FROM (SELECT * FROM table WHERE ...) WHERE ....
I run a mysql query that gets specific results from a table. I then want to print these results in two html tables. The first ordered by one column which is already done by putting ORDER BY into mysql query. But then I want to print the results ordered by a different column. However, I don't want to run a mysql query again as this is too slow.
So to sum up:
Is there a way to reorder the results of a mysql query?
(sorry if the question is unclear, it is my first time using the site.)
PHP has some really great sorting functions. I would most likely make a user-defined sorting function and use that with your result set:
http://php.net/manual/en/function.usort.php
Sorting with PHP is generally very fast. Faster than a 2nd query if your result set is not too large.
You can simply reorder the resultset yourself with one of the sorting methods in php.
http://php.net/manual/en/array.sorting.php
I assume you would want to use usort() here: http://php.net/manual/en/function.usort.php
Why not show it just once and use the jQuery Table sort plugin. Also, if you want to show it twice, there is no problem in making the table sortable.
The advantage would be performance increases as you are transferring the sort operation from server side (PHP) to client side (Javascript).
If you really want to use the sorting features in MySQL, as opposed to those in PHP, one option is to write your PHP code to query twice. In your first query:
SELECT id FROM table_name WHERE (whatever) ORDER BY first_criteria
Then in the second query, fetch rows:
WHERE id IN (2,17,388,etc.)
ORDER BY different_column
. . . passing the IDs from your first query into the IN clause, of course.
Not sure whether this would be faster or slower than sorting in PHP. Might be worth testing.