MySQL оптимизация запросов - присоединение и порядок

0

Мне нужна небольшая помощь в оптимизации оптимизации mysql. Это простой запрос, но все не так, и я не могу его найти: - (

У меня есть 2 таблицы: продукты ( > 40000 строк) и product_tags ( > 5 mil)

Существует соотношение между таблицами 1 → N. Каждый prdoduct может иметь много тегов в тегах табличного продукта.

У меня есть этот простой запрос:

EXPLAIN SELECT t.product_id, kwt.tag_id
FROM products AS t, product_tags AS kwt
WHERE 1
AND t.product_id = kwt.product_id
AND kwt.tag_id =11
ORDER BY t.order_date 

wchich возвращает 55 результатов.

Первая ситуация: если у меня есть эта таблица структуры таблиц:

CREATE TABLE IF NOT EXISTS `products` (
  `product_id` int(10) unsigned NOT NULL auto_increment,
  `product_source_id` smallint(5) unsigned NOT NULL,
  `order_date` int(10) unsigned NOT NULL,
  PRIMARY KEY  (`product_id`),
  KEY `order_date` (`order_date`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 ;


CREATE TABLE IF NOT EXISTS `product_tags` (
  `product_tag_id` int(10) unsigned NOT NULL auto_increment,
  `tag_id` int(10) unsigned NOT NULL,
  `product_id` int(11) NOT NULL,
  PRIMARY KEY  (`product_tag_id`),
  KEY `product_id` (`product_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8  ;

Тогда Объяснение запроса таково:

+----+-------------+-------+-------+---------------+------------+---------+---------------------------+-------+-------------+
| id | select_type | table | type  | possible_keys | key        | key_len | ref                       | rows  | Extra       |
+----+-------------+-------+-------+---------------+------------+---------+---------------------------+-------+-------------+
|  1 | SIMPLE      | t     | index | PRIMARY       | order_date | 4       | NULL                      | 45392 | Using index | 
|  1 | SIMPLE      | kwt   | ref   | product_id    | product_id | 4       | t.product_id          |     3 | Using where | 
+----+-------------+-------+-------+---------------+------------+---------+---------------------------+-------+-------------+

Он получает все строки из табличных продуктов, но с временной таблицей ничего нет.

Вторая ситуация: если я добавлю индекс для поля "tag_id" в product_tags, тогда изображение отличается:

+----+-------------+-------+--------+-------------------+---------+---------+-----------------------------+------+---------------------------------+
| id | select_type | table | type   | possible_keys     | key     | key_len | ref                         | rows | Extra                           |
+----+-------------+-------+--------+-------------------+---------+---------+-----------------------------+------+---------------------------------+
|  1 | SIMPLE      | kwt   | ref    | product_id,tag_id | tag_id  | 4       | const                       |   55 | Using temporary; Using filesort | 
|  1 | SIMPLE      | t     | eq_ref | PRIMARY           | PRIMARY | 4       | kwt.product_id              |    1 | Using where                     | 
+----+-------------+-------+--------+-------------------+---------+---------+-----------------------------+------+---------------------------------+

Теперь он выбирает только 55 строк, что правильно, но запрос havy:(

Где моя ошибка здесь?

Спасибо Nik

  • 0
    И никогда не используйте подразумеваемые объединения снова, это плохая методика программирования, которая устарела почти на 20 лет. К сожалению, вы пишете код в 2011 году, используя этот синтаксис. научиться использовать соединения explixit.
Теги:

1 ответ

1

вот что я сделал бы:

Прочитайте эти ресурсы

Редизайн вашей системы, чтобы использовать кластерный первичный ключ

Упрощенная схема:

drop table if exists products;
create table products
(
prod_id int unsigned not null auto_increment primary key,
name varchar(255) not null unique
)
engine = innodb; 

drop table if exists tags;
create table tags
(
tag_id mediumint unsigned not null auto_increment primary key,
name varchar(255) not null unique
)
engine = innodb; 

drop table if exists product_tags;
create table product_tags
(
tag_id mediumint unsigned not null,
prod_id int unsigned not null,
created_date date not null,
primary key (tag_id, prod_id), -- note the clustered composite index and the order !!
key (prod_id)
)
engine = innodb;

Проверить схему

select
 pt.tag_id,
 pt.prod_id
from
 product_tags pt
inner join products p on pt.prod_id = p.prod_id
where
 pt.tag_id = 11
order by
 pt.created_date
limit 10;

Я могу даже изменить product_tags PK на первичный ключ (tag_id, prod_id, created_date), но все зависит от типичных запросов, которые вы запускаете. Вы можете сделать из cc, просто создайте не кластеризованный вторичный индекс в созданную дату, если вы думаете, что это будет способствовать повышению производительности.

Надеюсь, что это поможет:)

  • 0
    Привет f00, отлично! Спасибо за ответ, я работаю!
  • 0
    круто - рад помочь :)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню