I need to optimize mysql select query or make it fasterMySQL query with join optimizationMySQL query optimization JOINMySQL query optimizationHow to optimize a count SQL query on a big tableOptimizing MySQL query with inner joinHow i can optimize my mysql query?Indexes in Mysql Query behaving indifferentlyOptimize mysql query with subqueriesOptimizing this MySQL query with a subquery insideMySQL - Slow Query when kept a View
Could Boris Johnson face criminal charges for illegally proroguing Parliament?
Why the first octet of a MAC address always end with a binary 0?
Using RECURSIVE in Virtual Layer
Why does `FindFit` fail so badly in this simple case?
What are one's options when facing religious discrimination at the airport?
Isn't the detector always measuring, and thus always collapsing the state?
As a team leader is it appropriate to bring in fundraiser candy?
Knights and Knaves: What does C say?
Booting Ubuntu from USB drive on MSI motherboard -- EVERYTHING fails
Did Joe Biden "stop a prosecution" into his son in Ukraine? And did he brag about stopping the prosecution?
Short story about a potato hotel that makes its guests into potatoes throughout the night
"Tenersi pronto" = to get ready or to be ready
Why do Russians sometimes spell "жирный" (fatty) as "жырный"?
What is the point of impeaching Trump?
What's the correct way to determine turn order in this situation?
Where does the image of a data connector as a sharp metal spike originate from?
How dangerous are my worn rims?
Is spot metering just an EV compensation?
What does a textbook look like while you are writing it?
Why has Speaker Pelosi been so hesitant to impeach President Trump?
Are there types of animals that can't make the trip to space? (physiologically)
Does it require less energy to reach the Sun from Pluto's orbit than from Earth's orbit?
Why do personal finance apps focus on outgoings rather than income
If I travelled back in time to invest in X company to make a fortune, roughly what is the probability that it would fail?
I need to optimize mysql select query or make it faster
MySQL query with join optimizationMySQL query optimization JOINMySQL query optimizationHow to optimize a count SQL query on a big tableOptimizing MySQL query with inner joinHow i can optimize my mysql query?Indexes in Mysql Query behaving indifferentlyOptimize mysql query with subqueriesOptimizing this MySQL query with a subquery insideMySQL - Slow Query when kept a View
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty
margin-bottom:0;
I have a select query, that selects over 50k records from mysql 5.5 database at once, and this amount is expected to grow. The query contains multiple subquery which is taking over 120s to execute.
Initially some of the sale_items
and stock
tables didnt have more that the ID keys, so i added some more
SELECT
`p`.`id` AS `id`,
`p`.`Name` AS `Name`,
`p`.`Created` AS `Created`,
`p`.`Image` AS `Image`,
`s`.`company` AS `supplier`,
`s`.`ID` AS `supplier_id`,
`c`.`name` AS `category`,
IFNULL((SELECT
SUM(`stocks`.`Total_Quantity`)
FROM `stocks`
WHERE (`stocks`.`Product_ID` = `p`.`id`)), 0) AS `total_qty`,
IFNULL((SELECT
SUM(`sale_items`.`quantity`)
FROM `sale_items`
WHERE (`sale_items`.`product_id` = `p`.`id`)), 0) AS `total_sold`,
IFNULL((SELECT
SUM(`sale_items`.`quantity`)
FROM `sale_items`
WHERE ((`sale_items`.`product_id` = `p`.`id`) AND `sale_items`.`Sale_ID` IN (SELECT
`refunds`.`Sale_ID`
FROM `refunds`))), 0) AS `total_refund`
FROM ((`products` `p`
LEFT JOIN `cats` `c`
ON ((`c`.`ID` = `p`.`cat_id`)))
LEFT JOIN `suppliers` `s`
ON ((`s`.`ID` = `p`.`supplier_id`)))
This is the explain result
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 20981 | |
| 2 | DERIVED | p | ALL | NULL | NULL | NULL | NULL | 20934 | |
| 2 | DERIVED | c | eq_ref | PRIMARY | PRIMARY | 4 | p.cat_id | 1 | |
| 2 | DERIVED | s | eq_ref | PRIMARY | PRIMARY | 4 | p.supplier_id | 1 | |
| 5 | DEPENDENT SUBQUERY | sale_items | ref | sales_items_product_id | sales_items_product_id | 5 | p.id | 33 | Using where |
| 6 | DEPENDENT SUBQUERY | refunds | index_subquery | IDX_refunds_sale_id | IDX_refunds_sale_id | 5 | func | 1 | Using index; Using where |
| 4 | DEPENDENT SUBQUERY | sale_items | ref | sales_items_product_id | sales_items_product_id | 5 | p.id | 33 | Using where |
| 3 | DEPENDENT SUBQUERY | stocks | ref | IDX_stocks_product_id | IDX_stocks_product_id | 5 | p.id | 1 | Using where |
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
I am expecting that the query takes less that 3s at most, but I cant seem to figure out the best way to optimize this query
mysql sql query-optimization
|
show 11 more comments
I have a select query, that selects over 50k records from mysql 5.5 database at once, and this amount is expected to grow. The query contains multiple subquery which is taking over 120s to execute.
Initially some of the sale_items
and stock
tables didnt have more that the ID keys, so i added some more
SELECT
`p`.`id` AS `id`,
`p`.`Name` AS `Name`,
`p`.`Created` AS `Created`,
`p`.`Image` AS `Image`,
`s`.`company` AS `supplier`,
`s`.`ID` AS `supplier_id`,
`c`.`name` AS `category`,
IFNULL((SELECT
SUM(`stocks`.`Total_Quantity`)
FROM `stocks`
WHERE (`stocks`.`Product_ID` = `p`.`id`)), 0) AS `total_qty`,
IFNULL((SELECT
SUM(`sale_items`.`quantity`)
FROM `sale_items`
WHERE (`sale_items`.`product_id` = `p`.`id`)), 0) AS `total_sold`,
IFNULL((SELECT
SUM(`sale_items`.`quantity`)
FROM `sale_items`
WHERE ((`sale_items`.`product_id` = `p`.`id`) AND `sale_items`.`Sale_ID` IN (SELECT
`refunds`.`Sale_ID`
FROM `refunds`))), 0) AS `total_refund`
FROM ((`products` `p`
LEFT JOIN `cats` `c`
ON ((`c`.`ID` = `p`.`cat_id`)))
LEFT JOIN `suppliers` `s`
ON ((`s`.`ID` = `p`.`supplier_id`)))
This is the explain result
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 20981 | |
| 2 | DERIVED | p | ALL | NULL | NULL | NULL | NULL | 20934 | |
| 2 | DERIVED | c | eq_ref | PRIMARY | PRIMARY | 4 | p.cat_id | 1 | |
| 2 | DERIVED | s | eq_ref | PRIMARY | PRIMARY | 4 | p.supplier_id | 1 | |
| 5 | DEPENDENT SUBQUERY | sale_items | ref | sales_items_product_id | sales_items_product_id | 5 | p.id | 33 | Using where |
| 6 | DEPENDENT SUBQUERY | refunds | index_subquery | IDX_refunds_sale_id | IDX_refunds_sale_id | 5 | func | 1 | Using index; Using where |
| 4 | DEPENDENT SUBQUERY | sale_items | ref | sales_items_product_id | sales_items_product_id | 5 | p.id | 33 | Using where |
| 3 | DEPENDENT SUBQUERY | stocks | ref | IDX_stocks_product_id | IDX_stocks_product_id | 5 | p.id | 1 | Using where |
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
I am expecting that the query takes less that 3s at most, but I cant seem to figure out the best way to optimize this query
mysql sql query-optimization
2
What does EXPLAIN show?
– PM 77-1
Mar 28 at 21:15
2
For query-optimization questions please include theSHOW CREATE TABLE
statements in your question.
– Willem Renzema
Mar 28 at 21:35
1
My first guess is that it's the derived tables which are costing you. Can you write your subqueries as regular outer joins ?
– Neville Kuyt
Mar 28 at 22:06
1
@Smith Yes it does. It will allow us to see the indexes you currently have, along with the column data types, to see if any are too large or are mismatched, along with other things critical to query optimization.
– Willem Renzema
Mar 28 at 22:56
1
If you have performance issues with subqueries in MySQL 5.5, the best advice is always to upgrade to a later version!
– oysteing
Mar 29 at 3:24
|
show 11 more comments
I have a select query, that selects over 50k records from mysql 5.5 database at once, and this amount is expected to grow. The query contains multiple subquery which is taking over 120s to execute.
Initially some of the sale_items
and stock
tables didnt have more that the ID keys, so i added some more
SELECT
`p`.`id` AS `id`,
`p`.`Name` AS `Name`,
`p`.`Created` AS `Created`,
`p`.`Image` AS `Image`,
`s`.`company` AS `supplier`,
`s`.`ID` AS `supplier_id`,
`c`.`name` AS `category`,
IFNULL((SELECT
SUM(`stocks`.`Total_Quantity`)
FROM `stocks`
WHERE (`stocks`.`Product_ID` = `p`.`id`)), 0) AS `total_qty`,
IFNULL((SELECT
SUM(`sale_items`.`quantity`)
FROM `sale_items`
WHERE (`sale_items`.`product_id` = `p`.`id`)), 0) AS `total_sold`,
IFNULL((SELECT
SUM(`sale_items`.`quantity`)
FROM `sale_items`
WHERE ((`sale_items`.`product_id` = `p`.`id`) AND `sale_items`.`Sale_ID` IN (SELECT
`refunds`.`Sale_ID`
FROM `refunds`))), 0) AS `total_refund`
FROM ((`products` `p`
LEFT JOIN `cats` `c`
ON ((`c`.`ID` = `p`.`cat_id`)))
LEFT JOIN `suppliers` `s`
ON ((`s`.`ID` = `p`.`supplier_id`)))
This is the explain result
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 20981 | |
| 2 | DERIVED | p | ALL | NULL | NULL | NULL | NULL | 20934 | |
| 2 | DERIVED | c | eq_ref | PRIMARY | PRIMARY | 4 | p.cat_id | 1 | |
| 2 | DERIVED | s | eq_ref | PRIMARY | PRIMARY | 4 | p.supplier_id | 1 | |
| 5 | DEPENDENT SUBQUERY | sale_items | ref | sales_items_product_id | sales_items_product_id | 5 | p.id | 33 | Using where |
| 6 | DEPENDENT SUBQUERY | refunds | index_subquery | IDX_refunds_sale_id | IDX_refunds_sale_id | 5 | func | 1 | Using index; Using where |
| 4 | DEPENDENT SUBQUERY | sale_items | ref | sales_items_product_id | sales_items_product_id | 5 | p.id | 33 | Using where |
| 3 | DEPENDENT SUBQUERY | stocks | ref | IDX_stocks_product_id | IDX_stocks_product_id | 5 | p.id | 1 | Using where |
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
I am expecting that the query takes less that 3s at most, but I cant seem to figure out the best way to optimize this query
mysql sql query-optimization
I have a select query, that selects over 50k records from mysql 5.5 database at once, and this amount is expected to grow. The query contains multiple subquery which is taking over 120s to execute.
Initially some of the sale_items
and stock
tables didnt have more that the ID keys, so i added some more
SELECT
`p`.`id` AS `id`,
`p`.`Name` AS `Name`,
`p`.`Created` AS `Created`,
`p`.`Image` AS `Image`,
`s`.`company` AS `supplier`,
`s`.`ID` AS `supplier_id`,
`c`.`name` AS `category`,
IFNULL((SELECT
SUM(`stocks`.`Total_Quantity`)
FROM `stocks`
WHERE (`stocks`.`Product_ID` = `p`.`id`)), 0) AS `total_qty`,
IFNULL((SELECT
SUM(`sale_items`.`quantity`)
FROM `sale_items`
WHERE (`sale_items`.`product_id` = `p`.`id`)), 0) AS `total_sold`,
IFNULL((SELECT
SUM(`sale_items`.`quantity`)
FROM `sale_items`
WHERE ((`sale_items`.`product_id` = `p`.`id`) AND `sale_items`.`Sale_ID` IN (SELECT
`refunds`.`Sale_ID`
FROM `refunds`))), 0) AS `total_refund`
FROM ((`products` `p`
LEFT JOIN `cats` `c`
ON ((`c`.`ID` = `p`.`cat_id`)))
LEFT JOIN `suppliers` `s`
ON ((`s`.`ID` = `p`.`supplier_id`)))
This is the explain result
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 20981 | |
| 2 | DERIVED | p | ALL | NULL | NULL | NULL | NULL | 20934 | |
| 2 | DERIVED | c | eq_ref | PRIMARY | PRIMARY | 4 | p.cat_id | 1 | |
| 2 | DERIVED | s | eq_ref | PRIMARY | PRIMARY | 4 | p.supplier_id | 1 | |
| 5 | DEPENDENT SUBQUERY | sale_items | ref | sales_items_product_id | sales_items_product_id | 5 | p.id | 33 | Using where |
| 6 | DEPENDENT SUBQUERY | refunds | index_subquery | IDX_refunds_sale_id | IDX_refunds_sale_id | 5 | func | 1 | Using index; Using where |
| 4 | DEPENDENT SUBQUERY | sale_items | ref | sales_items_product_id | sales_items_product_id | 5 | p.id | 33 | Using where |
| 3 | DEPENDENT SUBQUERY | stocks | ref | IDX_stocks_product_id | IDX_stocks_product_id | 5 | p.id | 1 | Using where |
+----+--------------------+------------+----------------+------------------------+------------------------+---------+---------------------------------
I am expecting that the query takes less that 3s at most, but I cant seem to figure out the best way to optimize this query
mysql sql query-optimization
mysql sql query-optimization
edited Apr 18 at 21:47
Smith
asked Mar 28 at 21:08


SmithSmith
3,14015 gold badges85 silver badges141 bronze badges
3,14015 gold badges85 silver badges141 bronze badges
2
What does EXPLAIN show?
– PM 77-1
Mar 28 at 21:15
2
For query-optimization questions please include theSHOW CREATE TABLE
statements in your question.
– Willem Renzema
Mar 28 at 21:35
1
My first guess is that it's the derived tables which are costing you. Can you write your subqueries as regular outer joins ?
– Neville Kuyt
Mar 28 at 22:06
1
@Smith Yes it does. It will allow us to see the indexes you currently have, along with the column data types, to see if any are too large or are mismatched, along with other things critical to query optimization.
– Willem Renzema
Mar 28 at 22:56
1
If you have performance issues with subqueries in MySQL 5.5, the best advice is always to upgrade to a later version!
– oysteing
Mar 29 at 3:24
|
show 11 more comments
2
What does EXPLAIN show?
– PM 77-1
Mar 28 at 21:15
2
For query-optimization questions please include theSHOW CREATE TABLE
statements in your question.
– Willem Renzema
Mar 28 at 21:35
1
My first guess is that it's the derived tables which are costing you. Can you write your subqueries as regular outer joins ?
– Neville Kuyt
Mar 28 at 22:06
1
@Smith Yes it does. It will allow us to see the indexes you currently have, along with the column data types, to see if any are too large or are mismatched, along with other things critical to query optimization.
– Willem Renzema
Mar 28 at 22:56
1
If you have performance issues with subqueries in MySQL 5.5, the best advice is always to upgrade to a later version!
– oysteing
Mar 29 at 3:24
2
2
What does EXPLAIN show?
– PM 77-1
Mar 28 at 21:15
What does EXPLAIN show?
– PM 77-1
Mar 28 at 21:15
2
2
For query-optimization questions please include the
SHOW CREATE TABLE
statements in your question.– Willem Renzema
Mar 28 at 21:35
For query-optimization questions please include the
SHOW CREATE TABLE
statements in your question.– Willem Renzema
Mar 28 at 21:35
1
1
My first guess is that it's the derived tables which are costing you. Can you write your subqueries as regular outer joins ?
– Neville Kuyt
Mar 28 at 22:06
My first guess is that it's the derived tables which are costing you. Can you write your subqueries as regular outer joins ?
– Neville Kuyt
Mar 28 at 22:06
1
1
@Smith Yes it does. It will allow us to see the indexes you currently have, along with the column data types, to see if any are too large or are mismatched, along with other things critical to query optimization.
– Willem Renzema
Mar 28 at 22:56
@Smith Yes it does. It will allow us to see the indexes you currently have, along with the column data types, to see if any are too large or are mismatched, along with other things critical to query optimization.
– Willem Renzema
Mar 28 at 22:56
1
1
If you have performance issues with subqueries in MySQL 5.5, the best advice is always to upgrade to a later version!
– oysteing
Mar 29 at 3:24
If you have performance issues with subqueries in MySQL 5.5, the best advice is always to upgrade to a later version!
– oysteing
Mar 29 at 3:24
|
show 11 more comments
1 Answer
1
active
oldest
votes
The query looks fine to me. You select all data and aggregate some of it. This takes time. Your explain plan shows there are indexes on the IDs, which is good. And at a first glance there is not much we seem to be able to do here...
What you can do, though, is provide covering indexes, i.e. indexes that contain all columns you need from a table, so the data can be taken from the index directly.
create index idx1 on cats(id, name);
create index idx2 on suppliers(id, company);
create index idx3 on stocks(product_id, total_quantity);
create index idx4 on sale_items(product_id, quantity, sale_id);
This can really boost your query.
What you can try About the query itself is to move the subqueries to the FROM
clause. MySQL's optimizer is not great, so although it should get the same execution plan, it may well be that it favors the FROM
clause.
SELECT
p.id,
p.name,
p.created,
p.image,
s.company as supplier,
s.id AS supplier_id,
c.name AS category,
COALESCE(st.total, 0) AS total_qty,
COALESCE(si.total, 0) AS total_sold,
COALESCE(si.refund, 0) AS total_refund
FROM products p
LEFT JOIN cats c ON c.id = p.cat_id
LEFT JOIN suppliers s ON s.id = p.supplier_id
LEFT JOIN
(
SELECT SUM(total_quantity) AS total
FROM stocks
GROUP BY product_id
) st ON st.product_id = p.id
LEFT JOIN
(
SELECT
SUM(quantity) AS total,
SUM(CASE WHEN sale_id IN (SELECT sale_id FROM refunds) THEN quantity END) as refund
FROM sale_items
GROUP BY product_id
) si ON si.product_id = p.id;
(If sale_id
is unique in refunds
, then you can even join it to sale_items
. Again: this should usually not make a difference, but in MySQL it may still. MySQL was once notorious for treating IN
clauses much worse than the FROM
clause. This may not be the case anymore, I don't know. You can try - if refunds.sale_id
is unique).
How fast is the original query after adding the indexes? After reformulating this way? (That is, is this a new starting point for the Question?)
– Rick James
Apr 19 at 5:05
add a comment
|
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/4.0/"u003ecc by-sa 4.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55406863%2fi-need-to-optimize-mysql-select-query-or-make-it-faster%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
The query looks fine to me. You select all data and aggregate some of it. This takes time. Your explain plan shows there are indexes on the IDs, which is good. And at a first glance there is not much we seem to be able to do here...
What you can do, though, is provide covering indexes, i.e. indexes that contain all columns you need from a table, so the data can be taken from the index directly.
create index idx1 on cats(id, name);
create index idx2 on suppliers(id, company);
create index idx3 on stocks(product_id, total_quantity);
create index idx4 on sale_items(product_id, quantity, sale_id);
This can really boost your query.
What you can try About the query itself is to move the subqueries to the FROM
clause. MySQL's optimizer is not great, so although it should get the same execution plan, it may well be that it favors the FROM
clause.
SELECT
p.id,
p.name,
p.created,
p.image,
s.company as supplier,
s.id AS supplier_id,
c.name AS category,
COALESCE(st.total, 0) AS total_qty,
COALESCE(si.total, 0) AS total_sold,
COALESCE(si.refund, 0) AS total_refund
FROM products p
LEFT JOIN cats c ON c.id = p.cat_id
LEFT JOIN suppliers s ON s.id = p.supplier_id
LEFT JOIN
(
SELECT SUM(total_quantity) AS total
FROM stocks
GROUP BY product_id
) st ON st.product_id = p.id
LEFT JOIN
(
SELECT
SUM(quantity) AS total,
SUM(CASE WHEN sale_id IN (SELECT sale_id FROM refunds) THEN quantity END) as refund
FROM sale_items
GROUP BY product_id
) si ON si.product_id = p.id;
(If sale_id
is unique in refunds
, then you can even join it to sale_items
. Again: this should usually not make a difference, but in MySQL it may still. MySQL was once notorious for treating IN
clauses much worse than the FROM
clause. This may not be the case anymore, I don't know. You can try - if refunds.sale_id
is unique).
How fast is the original query after adding the indexes? After reformulating this way? (That is, is this a new starting point for the Question?)
– Rick James
Apr 19 at 5:05
add a comment
|
The query looks fine to me. You select all data and aggregate some of it. This takes time. Your explain plan shows there are indexes on the IDs, which is good. And at a first glance there is not much we seem to be able to do here...
What you can do, though, is provide covering indexes, i.e. indexes that contain all columns you need from a table, so the data can be taken from the index directly.
create index idx1 on cats(id, name);
create index idx2 on suppliers(id, company);
create index idx3 on stocks(product_id, total_quantity);
create index idx4 on sale_items(product_id, quantity, sale_id);
This can really boost your query.
What you can try About the query itself is to move the subqueries to the FROM
clause. MySQL's optimizer is not great, so although it should get the same execution plan, it may well be that it favors the FROM
clause.
SELECT
p.id,
p.name,
p.created,
p.image,
s.company as supplier,
s.id AS supplier_id,
c.name AS category,
COALESCE(st.total, 0) AS total_qty,
COALESCE(si.total, 0) AS total_sold,
COALESCE(si.refund, 0) AS total_refund
FROM products p
LEFT JOIN cats c ON c.id = p.cat_id
LEFT JOIN suppliers s ON s.id = p.supplier_id
LEFT JOIN
(
SELECT SUM(total_quantity) AS total
FROM stocks
GROUP BY product_id
) st ON st.product_id = p.id
LEFT JOIN
(
SELECT
SUM(quantity) AS total,
SUM(CASE WHEN sale_id IN (SELECT sale_id FROM refunds) THEN quantity END) as refund
FROM sale_items
GROUP BY product_id
) si ON si.product_id = p.id;
(If sale_id
is unique in refunds
, then you can even join it to sale_items
. Again: this should usually not make a difference, but in MySQL it may still. MySQL was once notorious for treating IN
clauses much worse than the FROM
clause. This may not be the case anymore, I don't know. You can try - if refunds.sale_id
is unique).
How fast is the original query after adding the indexes? After reformulating this way? (That is, is this a new starting point for the Question?)
– Rick James
Apr 19 at 5:05
add a comment
|
The query looks fine to me. You select all data and aggregate some of it. This takes time. Your explain plan shows there are indexes on the IDs, which is good. And at a first glance there is not much we seem to be able to do here...
What you can do, though, is provide covering indexes, i.e. indexes that contain all columns you need from a table, so the data can be taken from the index directly.
create index idx1 on cats(id, name);
create index idx2 on suppliers(id, company);
create index idx3 on stocks(product_id, total_quantity);
create index idx4 on sale_items(product_id, quantity, sale_id);
This can really boost your query.
What you can try About the query itself is to move the subqueries to the FROM
clause. MySQL's optimizer is not great, so although it should get the same execution plan, it may well be that it favors the FROM
clause.
SELECT
p.id,
p.name,
p.created,
p.image,
s.company as supplier,
s.id AS supplier_id,
c.name AS category,
COALESCE(st.total, 0) AS total_qty,
COALESCE(si.total, 0) AS total_sold,
COALESCE(si.refund, 0) AS total_refund
FROM products p
LEFT JOIN cats c ON c.id = p.cat_id
LEFT JOIN suppliers s ON s.id = p.supplier_id
LEFT JOIN
(
SELECT SUM(total_quantity) AS total
FROM stocks
GROUP BY product_id
) st ON st.product_id = p.id
LEFT JOIN
(
SELECT
SUM(quantity) AS total,
SUM(CASE WHEN sale_id IN (SELECT sale_id FROM refunds) THEN quantity END) as refund
FROM sale_items
GROUP BY product_id
) si ON si.product_id = p.id;
(If sale_id
is unique in refunds
, then you can even join it to sale_items
. Again: this should usually not make a difference, but in MySQL it may still. MySQL was once notorious for treating IN
clauses much worse than the FROM
clause. This may not be the case anymore, I don't know. You can try - if refunds.sale_id
is unique).
The query looks fine to me. You select all data and aggregate some of it. This takes time. Your explain plan shows there are indexes on the IDs, which is good. And at a first glance there is not much we seem to be able to do here...
What you can do, though, is provide covering indexes, i.e. indexes that contain all columns you need from a table, so the data can be taken from the index directly.
create index idx1 on cats(id, name);
create index idx2 on suppliers(id, company);
create index idx3 on stocks(product_id, total_quantity);
create index idx4 on sale_items(product_id, quantity, sale_id);
This can really boost your query.
What you can try About the query itself is to move the subqueries to the FROM
clause. MySQL's optimizer is not great, so although it should get the same execution plan, it may well be that it favors the FROM
clause.
SELECT
p.id,
p.name,
p.created,
p.image,
s.company as supplier,
s.id AS supplier_id,
c.name AS category,
COALESCE(st.total, 0) AS total_qty,
COALESCE(si.total, 0) AS total_sold,
COALESCE(si.refund, 0) AS total_refund
FROM products p
LEFT JOIN cats c ON c.id = p.cat_id
LEFT JOIN suppliers s ON s.id = p.supplier_id
LEFT JOIN
(
SELECT SUM(total_quantity) AS total
FROM stocks
GROUP BY product_id
) st ON st.product_id = p.id
LEFT JOIN
(
SELECT
SUM(quantity) AS total,
SUM(CASE WHEN sale_id IN (SELECT sale_id FROM refunds) THEN quantity END) as refund
FROM sale_items
GROUP BY product_id
) si ON si.product_id = p.id;
(If sale_id
is unique in refunds
, then you can even join it to sale_items
. Again: this should usually not make a difference, but in MySQL it may still. MySQL was once notorious for treating IN
clauses much worse than the FROM
clause. This may not be the case anymore, I don't know. You can try - if refunds.sale_id
is unique).
edited Mar 28 at 22:07
answered Mar 28 at 22:01
Thorsten KettnerThorsten Kettner
55.4k3 gold badges28 silver badges48 bronze badges
55.4k3 gold badges28 silver badges48 bronze badges
How fast is the original query after adding the indexes? After reformulating this way? (That is, is this a new starting point for the Question?)
– Rick James
Apr 19 at 5:05
add a comment
|
How fast is the original query after adding the indexes? After reformulating this way? (That is, is this a new starting point for the Question?)
– Rick James
Apr 19 at 5:05
How fast is the original query after adding the indexes? After reformulating this way? (That is, is this a new starting point for the Question?)
– Rick James
Apr 19 at 5:05
How fast is the original query after adding the indexes? After reformulating this way? (That is, is this a new starting point for the Question?)
– Rick James
Apr 19 at 5:05
add a comment
|
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55406863%2fi-need-to-optimize-mysql-select-query-or-make-it-faster%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
2
What does EXPLAIN show?
– PM 77-1
Mar 28 at 21:15
2
For query-optimization questions please include the
SHOW CREATE TABLE
statements in your question.– Willem Renzema
Mar 28 at 21:35
1
My first guess is that it's the derived tables which are costing you. Can you write your subqueries as regular outer joins ?
– Neville Kuyt
Mar 28 at 22:06
1
@Smith Yes it does. It will allow us to see the indexes you currently have, along with the column data types, to see if any are too large or are mismatched, along with other things critical to query optimization.
– Willem Renzema
Mar 28 at 22:56
1
If you have performance issues with subqueries in MySQL 5.5, the best advice is always to upgrade to a later version!
– oysteing
Mar 29 at 3:24