Мне нужна небольшая помощь в оптимизации оптимизации 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
вот что я сделал бы:
http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html
http://www.xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/
Упрощенная схема:
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, просто создайте не кластеризованный вторичный индекс в созданную дату, если вы думаете, что это будет способствовать повышению производительности.
Надеюсь, что это поможет:)