I am trying to optimize the following modified MySQL query from OsCommerce:
select distinct p.products_id, pd.products_name, m.manufacturers_name, s.specials_new_products_price from products p
inner join products_description pd on p.products_id = pd.products_id
inner join products_to_categories p2c on p.products_id = p2c.products_id
left join manufacturers m on p.manufacturers_id = m.manufacturers_id
left join specials s on p.products_id = s.products_id and s.specials_b2bgroup =0
where p.products_status = '1' and p.products_model not like '%_VIP' and pd.language_id = '4' and p2c.categories_id = '1574'
order by p.products_ordernum, p.products_model
Running explain on production server it seems that no indexes are used for table products at join:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE p ALL PRIMARY NULL NULL NULL 6729 Using where; Using temporary; Using filesort
1 SIMPLE m eq_ref PRIMARY PRIMARY 4 p.manufacturers_id 1
1 SIMPLE s ref products_id products_id 4 p.products_id 2
1 SIMPLE pd eq_ref PRIMARY PRIMARY 8 p.products_id,const 1
1 SIMPLE p2c eq_ref PRIMARY PRIMARY 8 pd.products_id,const 1 Using where; Using index; Distinct
The schema for table products is the following:
CREATE TABLE IF NOT EXISTS `products` (
`products_id` int(11) NOT NULL auto_increment,
`products_model` varchar(50) default NULL,
`products_image` varchar(250) default NULL,
`products_price` decimal(15,4) NOT NULL default '0.0000',
`products_date_added` datetime NOT NULL default '0000-00-00 00:00:00',
`products_last_modified` datetime default NULL,
`products_date_available` datetime default NULL,
`products_weight` decimal(5,2) NOT NULL default '0.00',
`products_status` tinyint(1) NOT NULL default '0',
`products_showprod` tinyint(1) NOT NULL default '0',
`products_showprice` tinyint(1) NOT NULL default '0',
`products_ordernum` int(6) NOT NULL default '100',
`products_tax_class_id` int(11) NOT NULL default '0',
`manufacturers_id` int(11) default NULL,
PRIMARY KEY (`products_id`),
KEY `idx_products_model` (`products_model`),
) ENGINE=MyISAM DEFAULT CHARSET=greek AUTO_INCREMENT=1;
My server’s MySQL version is 5.0.92. Any thoughts on where to look for a solution are realy welcome!
2
Answers
products
is the leading (outermost) table in the nested loops, so the indexes used to access this table have nothing to do with the joins.This condition:
is not sargable.
You could try creating an index on
products (status)
, if it’s selective enough (i. e. there are few values withstatus = 1
)There are only two constraints in that query on the
products
table, which you have declared as the “master” table (because everything else isJOIN ON
):products_status
(not indexed) andproducts_model
. ButNOT LIKE '%...'
is not an indexable constraint, so it is faster to do a simple scan.The index would be useful if the
%
came in the middle or end of theLIKE
pattern. Even so, theNOT
might still make the linear scan faster.