I need to lookup all my products (sku's) their latest stock quantity.
I have one table (called "stock") with 315k+ records containing this information (a new batch of data is added every day, for most sku's). The reference data is in another table (called "stockfile").
This is the query to do it:
SELECT s1 . * , f1 . *
FROM stock s1
JOIN stockfile f1 ON ( s1.stockfileid = f1.stockfileid )
LEFT OUTER JOIN ( stock s2
JOIN stockfile f2 ON ( s2.stockfileid = f2.stockfileid )
) ON ( s1.sku = s2.sku
AND ( f1.date < f2.date
OR f1.date = f2.date
AND f1.stockfileid < f2.stockfileid) )
WHERE s2.sku IS NULL
These are the table definitions
SHOW CREATE TABLE
stock:
CREATE TABLE `stock` (
`stockid` bigint(20) NOT NULL AUTO_INCREMENT,
`sku` char(25) NOT NULL,
`quantity` int(5) NOT NULL,
`creationdate` datetime NOT NULL,
`stockfileid` smallint(5) unsigned NOT NULL,
`touchdate` datetime NOT NULL,
PRIMARY KEY (`stockid`),
KEY `stock_sku` (`sku`),
KEY `stock_stockfileid` (`stockfileid`)
) ENGINE=MyISAM AUTO_INCREMENT=316039 DEFAULT CHARSET=latin1
SHOW CREATE TABLE
stockfile:
CREATE TABLE `stockfile` (
`stockfileid` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`filename` varchar(25) NOT NULL,
`creationdate` datetime DEFAULT NULL,
`touchdate` datetime DEFAULT NULL,
`date` datetime DEFAULT NULL,
`begindate` datetime DEFAULT NULL,
`enddate` datetime DEFAULT NULL,
PRIMARY KEY (`stockfileid`),
KEY `stockfile_date` (`date`)
) ENGINE=MyISAM AUTO_INCREMENT=266 DEFAULT CHARSET=latin1
Without any extra indexes it takes... forever. I added these and it sped up to about 250 seconds:
CREATE INDEX stock_sku ON stock(sku);
CREATE INDEX stock_stockfileid ON stock(stockfileid);
CREATE INDEX stockfile_date ON stockfile(date);
This is the EXPLAIN
on the original query, with these indexes.
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE s1 ALL stock_stockfileid NULL NULL NULL 316038
1 SIMPLE f1 eq_ref PRIMARY PRIMARY 2 kompare.s1.stockfileid 1
1 SIMPLE s2 ref stock_sku,stock_stockfileid stock_sku 25 kompare.s1.sku 12 Using where
1 SIMPLE f2 eq_ref PRIMARY,stockfile_date PRIMARY 2 kompare.s2.stockfileid 1
Is there another way to speed things up?
- Thanks to Bill Karwin for solving the original query!