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 ....
Related
mysql query very slow but i use "group by" function...
i remove group by query and query very fast.
How can I solve this problem?
my query code:
$myquery1 = mysql_query("SELECT * FROM konucuklar
WHERE status=''
and category='football'
GROUP BY matchhour
ORDER BY id asc");
while($myquery1record = mysql_fetch_array($myquery1)){
$myquery2 = mysql_query("SELECT * FROM konucuklar
WHERE mactarihi='$bugunt'
and statu=''
and kategori='futbol'
and macsaati='$myquery1record[matchhour]'
ORDER BY id asc");
$toplams=#mysql_num_rows($myquery2);
while ($myquery2record=mysql_fetch_array($myquery2)) {
// code
}
}
}
Your first query does not comply with SQL standards and will be processed by mysql only if strict sql mode is not enabled.
You are issuing the 2nd query in a loop based on the results returned by the 1st query. So, if the 1st query returns 10 rows, then you will execute the 2nd query 10 times. This is very slow. You should rewrite the 2 queries as one, since both queries query the same table and have almost the same where criteria.
No idea what the 2nd while loop does, as I can't see where $listele is defined.
The slow down might not be related to the GROUP BY clause. Try adding an index on columns you need to .
Link to understand index : http://www.tutorialspoint.com/sql/sql-indexes.htm
MySQL Profiling might also help you in your endeavour
Your queries are not optimized and probably could be done better in other way incluiding using only one composed query (JOIN) to fetch all data at once.
Also if your tables have lots of items is good practice to create INDEXES to the fields uses in the common queries for the filter to make the search faster.
Example, your firs select has this complexity (and probably is not well formed)
SELECT * FROM konucuklar WHERE status=''
and category='football'
GROUP BY matchhour
ORDER BY id asc
But is used only to get the matchhour for the second query. The minimal optimization is to use a query to fetch only the required field.
SELECT DISTINCT matchhour FROM konucuklar WHERE status='' and category='football'
i am running queries on a table that has thousands of rows:
$sql="select * from call_history where extension_number = '0536*002' and flow = 'in' and DATE(initiated) = '".date("Y-m-d")."' ";
and its taking forever to return results.
The SQL itself is
select *
from call_history
where extension_number = '0536*002'
and flow = 'in'
and DATE(initiated) = 'dateFromYourPHPcode'
is there any way to make it run faster? should i put the where DATE(initiated) = '".date("Y-m-d")."' before the extension_number where clause?
or should i select all rows where DATE(initiated) = '".date("Y-m-d")."' and put that in a while loop then run all my other queries (where extension_number = ...) whthin the while loop?
Here are some suggestions:
1) Replace SELECT * by the only fields you want.
2) Add indexing on the table fields you want as output.
3) Avoid running queries in loops. This causes multiple requests to SQL server.
4) Fetch all the data at once.
5) Apply LIMIT tag as and when required. Don't select all the records.
6) Fire two different queries: one for counting total number of records and other for fetching number of records per page (e.g. 10, 20, 50, etc...)
7) If applicable, create Database Views and get data from them instead of tables.
Thanks
The order of clauses under WHERE is irrelevant to optimization.
Pro-tip, also suggested by somebody else: Never use SELECT * in a query in a program
unless you have a good reason to do so. "I don't feel like writing out the names of the columns I need" isn't a good reason. Always enumerate the columns you need. MySQL and other database systems can often optimize things in surprising ways when the list of data columns you need is available.
Your query contains this selection criterion.
AND DATE(initiated) = 'dateFromYourPHPcode'
Notice that this search criterion takes the form
FUNCTION(column) = value
This form of search defeats the use of any index on that column. Your initiated column has a TIMESTAMP data type. Try this instead:
AND initiated >= 'dateFromYourPHPcode'
AND initiated < 'dateFromYourPHPcode' + INTERVAL 1 DAY
This will find all the initiated items in the particular day. And, because it doesn't use a function on the column value it can use an index range scan to do that, which performs well. It may, or may not, also help without an index. It's worth a try.
I suspect your ideal index for this particular search would created by
ALTER TABLE call_history
ADD INDEX flowExtInit (flow, extension_number, initiated)
You should ask the administrator of the database to add this index if your query needs good performance.
You should add index to your table. This way MySql will fetch faster. I have not tested but command should be like this:
ALTER TABLE `call_history ` ADD INDEX `callhistory` (`extension_number`,`flow`,`extension_number`,`DATE(initiated)`);
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.
I was wondering which of these would be faster (performance-wise) to query (on MySQL 5.x CentOS 5.x if this matters):
SELECT * FROM table_name WHERE id=1;
SELECT * FROM table_name WHERE id=2;
.
.
.
SELECT * FROM table_name WHERE id=50;
or...
SELECT * FROM table_name WHERE id IN (1,2,...,50);
I have around 50 ids to query for. I know usually DB connections are expensive, but I've seen the IN clause isn't so fast either [sometimes].
I'm pretty sure the second option gives you the best performance; one query, one result. You have to start looking for > 100 items before it may become an issue.
See also the accepted answer from here: MySQL "IN" operator performance on (large?) number of values
IMHO you should try it and measure response time: IN should give you better performances...
Anyway if your ids are sequential you could try
SELECT * FROM table_name WHERE id BETWEEN 1 AND 50
Here is another post where the discuss the performance of using OR vs IN. IN vs OR in the SQL WHERE Clause
You suggested using multiple queries, but using OR would also work.
2nd will be faster because resources are consumed when query gets interpreted and during php communication with mysql for sending query and waiting for result , if your data is sequential you can also do just
SELECT * FROM table_name WHERE id <= 50;
I was researching this after experimenting with 3000+ values in an IN clause. It turned out to be multitudes faster than individual SELECTs since the column referenced in the IN was not keyed. My guess is that in my case it only needed to build a temporary index for that column once instead of 3000 separate times.
Is there a way of running a single MySQL query, which selects data from various tables and returns each table individually that can be assigned to an array, in PHP, instead of a query for each table and assigning the results manually to the array?
For instance
// Interpretation:
$multiple = mysql_query("select * from table_a; select * from table_b;");
foreach ($multiple as $table => $results) {
$tables[$table] = $results;
}
instead of:
$tables = array (
"table_a" => mysql_query ("select * from table_a;"),
"table_b" => mysql_query ("select * from table_b;"),
);
Any guidance will be most appreciated. Thank you.
Not without nasty SQL tricks. I don't think your suggested way is any more efficient though. If the two tables are huge, it will be better to break the huge request into two not-so-huge requests.
If they are relatively tiny, it still won't make much of a difference.
However, if bandwidth is at a premium, I'm still not sure there's anyway to grab two tables in one query.
Why don't you use union ?
$multiple = mysql_query("select 'table_a', table_a.* from table_a union select 'table_b', table_b.* from table_b");
$tables=array();
foreach ($multiple as $table => $results)
{
$tables[$results[0]] = array_shift($results);
}
If the number of columns in table is different just put NULL instead of missing columns. I will sugest not to use * at all unless in testing.
example query for different number of columns:
select 'table_a', table_a.col1, table_a.col2, table_a.col3 from table_a union select 'table_b', table_b.col1, table_b.col2, NULL from table_b;
open two DB links, do querys with mysql_unbuffered_query. Mysql_unbuffered_query executes the query but returns inmediately to php code, while mysql engine proccess the query. later, when you use mysql_fetch_row and so, is when the data is REALLY retrieved from mysql engine.
this way, if you do the two querys in two db links (two mysql_connect), each query for each link, you can start to work with the first, and the mysql engine is 'caching/working' in the second while your php code is executing.
Also, if you use unbuffered queries, you can't do mysql_num_rows or so, because can be that the complete resultset is not in memory yet.
mysqli->query("...", MYSQLI_ASYNC) or PDO/MYSQL is a better and modern way to do this, but you need a mysqlnd or a libmysql compatible with ASYNC queries.