Currently I'm working on a project which requires me to write an API for my users. I have written the following SQL statement so far and tested it on my localhost over my php:
SELECT topquery.kind_id,
topquery.image,
topquery.id,
userquery.user_name
FROM `order` AS topquery,
`user` AS userquery
WHERE userquery.user_id = topquery.user_id
AND topquery.id IN
(SELECT MIN(id)
FROM `order` AS mainquery
WHERE user_id != '$vUserId'
AND id NOT IN
(SELECT order_id
FROM history
WHERE user_id = '$vUserId')
AND kind_id NOT IN
(SELECT o.kind_id
FROM history h
INNER JOIN `order` o ON h.order_id = o.id
WHERE h.user_id = '$vUserId')
AND actions > 0
AND kind = '1'
GROUP BY kind_id)
ORDER BY vip DESC
LIMIT 35
This query takes about 0.5 secs on my localhost, and takes ~1.4 seconds on my server.
Now my question: Is it possible that the speed of SQL queries can vary for each mysql version? Or is my query just not "optimized" enough?
Yes, it will be different, because every version of sql has different tweaks to be optimized or code path or algorithm processing speed. I think the latest version would faster than previous one.
off topic advice, but I wanted formatting so a comment isn't enough
You commence your query using a join predicate within the where clause
FROM `order` AS topquery,
`user` AS userquery
WHERE userquery.user_id = topquery.user_id
Yet deeper into the query you do use INNER JOIN syntax. So why not do this throughout?
FROM `order` AS topquery,
INNER JOIN `user` AS userquery ON userquery.user_id = topquery.user_id
Stick to using only explicit joins. Don't allow yourself to use commas between tables in the from clause. Don't "mix and match" join syntax, this leads to maintenance problems and possible bugs.
Here I outline a diagnostic for your case, and then you can ascertain whether or not the speed is still actually a problem:
Network. Im not sure if thats time executed purely from SQL or if network time is in there as well. Your network call will incur an overhead.
It depends on what your server is, but if your environments are matched, it is almost always definitely because there is substantially more data in your server database than your localhost.
One of the plusses of having a shared dev server in a corporate context is that someone will probably put some data on there for you every so often, so everyone doesnt have to copy everything down to their machine to work with a real size data set. More data = more work = takes longer, simple as that.
You have a discrepancy in your database schema. If you arent in the position to rebuild your database in one command, you might've added an index on your localhost and forgot about it. You can use a schema tool to get the differences between your localhost and your database. I like SQLYog. I think Mysql workbench does it as well.
You have a discrepancy in your hardware. Ie your server is a 486 with 4mb of RAM.
Difference in performance between servers
Yes, performance can change between different MySQL versions. The reason is because the entire software might change, including the MySQL optimizer which calculates the plan that the query will be executed by.
Few factors I would check before deciding whether the MySQL version is the root cause are:
Query Performance
In addition, I looked at your query and it looks like it can be better optimized.
(I used EverSQL SQL Query Optimizer to get the recommendations - disclaimer, I'm a co-founder of EverSQL and humbly provide these suggestions):
This is how the queries will look like after optimization:
create table temp as
SELECT
o.kind_id
FROM
history h
INNER JOIN `order` o ON h.order_id = o.id
WHERE
h.user_id = '$vUserId';
CREATE INDEX kind_id on temp(kind_id);
create table temp2 as
SELECT
MIN(id) as id
FROM
`order` AS mainquery
left join history h on mainquery.id=h.order_id
left join temp t on mainquery.kind_id=t.kind_id
WHERE
user_id != '$vUserId'
AND h.order id is null
and t.kind_id is null
AND actions > 0
AND kind = '1'
GROUP BY
kind_id;
CREATE INDEX id on temp2(id);
SELECT
topquery.kind_id,
topquery.image,
topquery.id,
userquery.user_name
FROM
`order` AS topquery,
`user` AS userquery,
temp2 AS temp
WHERE
userquery.user_id = topquery.user_id
AND topquery.id = temp.id
ORDER BY vip DESC
LIMIT 35
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.