I am having some troubles trying to optimize the definition of a view in my db.
The query sums 2 kind of quantities based on LEFT JOIN of 3 tables, described as the stocking view within this fiddle: SQL Fiddle
Basically I tried to create indexes or re-define the view, but every time the execution time is ~5.5s even if the larges of the tables - the rows table in the fiddle - has ~15K records.
The thing that I'm struggling to understand is why, even if an index is defined for the GROUP BY column statement - shown in the possible_keys result for the EXPLAIN command - no index is used.
--- EDIT ---
I think that I've found my issue, the use of LEFT JOIN instead of INNER JOIN on the head table and the rows table was slowing the query down due to MySQL internal design
Also usign a coverage index on the head table for ID and CLOSING_DATE better tune up the performaces
DDLs AND RECORDS
CREATE TABLE head (
ID varchar(30) NOT NULL,
CLOSING_DATE int NOT NULL,
PRIMARY KEY(ID),
KEY CLOSING (ID, CLOSING_DATE)
);
CREATE TABLE `rows` (
ID int NOT NULL,
HEAD_ID varchar(30) NOT NULL,
PRODUCT varchar(30) NOT NULL,
QTY decimal(16,6) NOT NULL,
STKQTY decimal(16,6) NOT NULL,
PRIMARY KEY(ID),
KEY PROD(PRODUCT),
KEY HEAD(HEAD_ID)
);
CREATE TABLE production (
ID int NOT NULL,
ROW_ID int NOT NULL,
QTY decimal(16,6) NOT NULL,
PRIMARY KEY(ID),
KEY ROWID(ROW_ID)
);
CREATE VIEW row_prod AS(
SELECT ROW_ID, SUM(QTY) AS PRD_QTY FROM production WHERE ROW_ID <> 0 GROUP BY ROW_ID
);
CREATE VIEW stocking AS(
SELECT
`rows`.PRODUCT,
SUM(`rows`.STKQTY) AS STKQTY,
GREATEST(SUM(CASE WHEN CLOSING_DATE <> 0 THEN 0 ELSE (`rows`.QTY - `rows`.STKQTY - COALESCE(row_prod.PRD_QTY, 0)) END), 0) AS RESQTY
FROM
`rows`
INNER JOIN
head ON head.ID = `rows`.HEAD_ID
LEFT JOIN
row_prod ON row_prod.ROW_ID = `rows`.ID
GROUP BY
`rows`.PRODUCT
);
INSERT INTO head (ID, CLOSING_DATE) VALUES
(1, 0),
(2, 20220601),
(3, 0);
INSERT INTO `rows` (ID, HEAD_ID, PRODUCT, QTY, STKQTY) VALUES
(1, 1, 'PROD_A', 10, 2),
(2, 1, 'PROD_B', 5, 0),
(3, 2, 'PROD_A', 15, 6),
(4, 2, 'PROD_D', 7, 0),
(5, 2, 'PROD_E', 12, 4),
(6, 3, 'PROD_A', 3, 0),
(7, 3, 'PROD_B', 1, 1),
(8, 3, 'PROD_F', 5, 5),
(9, 3, 'PROD_G', 6, 6);
INSERT INTO production (ID, ROW_ID, QTY) VALUES
(1, 1, 1),
(2, 3, 6),
(3, 4, 10);
EXPLAIN DETAILS
id|select_type|table |partitions|type |possible_keys |key |key_len|ref |rows|filtered|Extra |
--+-----------+----------+----------+-------+----------------+--------+-------+---------------+----+--------+---------------------------------------------+
1|PRIMARY |<derived2>| |ALL | | | | | 6| 100.0| |
2|DERIVED |head | |index |PRIMARY,CLOSING |CLOSING |96 |rows.HEAD_ID | 3| 100.0|Using index; Using temporary; Using filesort |
2|DERIVED |rows | |ref |HEAD,PROD |HEAD |92 |head.ID | 1| 100.0| |
2|DERIVED |<derived3>| |ref | | |4 |rows.ID | 2| 100.0| |
3|DERIVED |production| |index |ROWID |ROWID |4 | | 3| 100.0|Using where |