带有标签和GROUP_CONCAT的产品视图

时间:2011-05-13 15:40:53

标签: mysql view tags group-concat

我在我的应用上使用Sphinx进行全文搜索。我使用view来过滤products表中的数据,Sphinx对此视图进行索引。现在我在产品表下面有一个带有相关标签的硬编码字段,但这不太好,因为标签可能会改变,我每次都必须操纵硬编码字段。

所以我想我可以使用GROUP_CONCAT创建视图,使用如下语法列出所有相关标签:

SELECT p.id AS id, GROUP_CONCAT(t.tag SEPARATOR '|') AS tags,
UNIX_TIMESTAMP(p.created) AS created
FROM products p
INNER JOIN products_tags pt ON pt.product_id = p.id
INNER JOIN tags t ON t.id = pt.tag_id
AND p.deleted = 0
AND (p.images IS NOT NULL OR p.images <> '')
AND p.status LIKE 'listed'
GROUP BY p.id;

此查询的问题是运行需要很长时间。这真的很慢。要仅检索一条记录,最多需要5秒钟。这是EXPLAIN输出:

1, SIMPLE, pt, ALL, , , , , 165029, Using temporary; Using filesort
1, SIMPLE, p, eq_ref, PRIMARY, PRIMARY, 4, trych_default.pt.product_id, 1, Using where
1, SIMPLE, t, eq_ref, PRIMARY, PRIMARY, 4, trych_default.pt.tag_id, 1, 

我想知道是否有任何方法可以改进查询或者可能是我问题的更好解决方案。谢谢!

1 个答案:

答案 0 :(得分:3)

你可能错过了一个索引。使用以下模式,同一查询命中每个表的索引:

CREATE TABLE `products` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `deleted` tinyint(1) unsigned NOT NULL DEFAULT '0',
  `status` varchar(255) NOT NULL DEFAULT 'listed',
  `images` varchar(255) DEFAULT NULL,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `tags` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `tag` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `products_tags` (
  `product_id` int(11) NOT NULL,
  `tag_id` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`product_id`,`tag_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

以下是EXPLAIN查询的结果:

EXPLAIN SELECT p.id AS id, GROUP_CONCAT(t.tag SEPARATOR '|') AS tags,
UNIX_TIMESTAMP(p.created) AS created
FROM products p
INNER JOIN products_tags pt ON pt.product_id = p.id
INNER JOIN tags t ON t.id = pt.tag_id
WHERE p.deleted = 0
AND (p.images IS NOT NULL OR p.images <> '')
AND p.status LIKE 'listed'
GROUP BY p.id;

+----+-------------+-------+--------+---------------+---------+---------+----------------+------+-------------+
| id | select_type | table | type   | possible_keys | key     | key_len | ref            | rows | Extra       |
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+-------------+
|  1 | SIMPLE      | p     | index  | PRIMARY       | PRIMARY | 4       | NULL           |    1 | Using where |
|  1 | SIMPLE      | pt    | ref    | PRIMARY       | PRIMARY | 4       | test.p.id      |    1 | Using index |
|  1 | SIMPLE      | t     | eq_ref | PRIMARY       | PRIMARY | 4       | test.pt.tag_id |    1 |             |
+----+-------------+-------+--------+---------------+---------+---------+----------------+------+-------------+
3 rows in set (0.00 sec)