MySQL объяснение показывает, что индексы главной таблицы не используются на производственном сервере - PullRequest
1 голос
/ 15 марта 2011

Я пытаюсь оптимизировать следующий модифицированный MySQL-запрос от 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

При запуске объяснения на рабочем сервере кажется, что индексы для табличных продуктов при объединении не используются:

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

Схема для табличных продуктов следующая:

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;

Версия MySQL для моего сервера - 5.0.92.Любые мысли о том, где искать решение, действительно приветствуются!

Ответы [ 2 ]

0 голосов
/ 15 марта 2011

В этом запросе есть только два ограничения для таблицы products, которые вы объявили как «главную» таблицу (поскольку все остальное - JOIN ON): products_status (не проиндексировано) и products_model. Но NOT LIKE '%...' не является индексируемым ограничением, поэтому быстрее выполнить простое сканирование.

Индекс будет полезен, если % находится в середине или конце шаблона LIKE. Тем не менее, NOT может все же ускорить линейное сканирование.

0 голосов
/ 15 марта 2011

products является ведущей (самой внешней) таблицей во вложенных циклах, поэтому индексы, используемые для доступа к этой таблице, не имеют ничего общего с объединениями.

Это условие:

p.products_model not like '%_VIP'

не может быть sargable.

Вы можете попытаться создать индекс на products (status), если он достаточно избирателен (т. Е. Есть несколько значений с status = 1)

...