MySQL联盟在视图中

时间:2013-07-22 09:05:31

标签: mysql database-design

我有2个大表,product和product_variants。 目前我正在使用MySQL视图,因为我多次需要这个SQL语句。 数据库结构无法更改atm。

产品:
ID | IsMaster | EAN |名称|价格......

Product_Variants:
ID | PID(Product.ID上的FK)| IsMaster | EAN |名称|价格......

视图my_view包含这样的选择:

(SELECT * FROM `product`) UNION (SELECT * FROM `product_variants`)

当我现在正在进行这样的查询时:

SELECT * FROM my_view WHERE EAN = '11110'

大约需要0.5到1秒。 如果我通过向每个子查询添加where直接使用视图的内容,它会超快(~0,004秒):

(SELECT * FROM `product` WHERE EAN = '11110') UNION (SELECT * FROM `product_variants` WHERE EAN = '11110')

如何在视图中使用更快的方法?我需要更改为MySQL功能吗?

TIA 马特

4 个答案:

答案 0 :(得分:2)

您可能会发现这篇文章很有用 - http://www.mysqlperformanceblog.com/2007/08/12/mysql-view-as-performance-troublemaker/

基本前提是MySQL视图有助于用优化代码编写简单的SQL 而不是

[The] VIEW只是作为宏或临时表扩展,在这种情况下,VIEW具体化为临时表(没有索引!)

没有索引=慢选择查询。

答案 1 :(得分:2)

基本问题是视图中的联合被执行(没有where子句的好处)之前应用where子句来过滤这些行。

效果是从两个表中选择每一行到一个巨大的临时表中,然后在该临时表上应用where子句,当然没有索引的好处(即使基表上存在一个)。

您可以尝试使用UNION ALL(而不仅仅是UNION),因为UNION ALL会保留所有行,而UNION会丢弃重复项,这会从结果中屏蔽基础表由于重复数据删除过程。


真正的问题是数据库设计 - 两个表非常相似,很明显应该只有一个isVariant列来区分行类型。如果您无法更改表,则可以创建一个新表:

NewProduct
ID | PID (fk to self for variants, null otherwise) | IsMaster | IsVariant | EAN | Name | Price ..

并将索引放在您正在搜索的任何列上(在这种情况下为EAN)。

您可以轻松填充一次。为了使其与旧表保持同步,您可以在产品信息更改时手动截断并重新运行填充脚本,或者在旧表上使用触发器以使其自动保持同步。这取决于您网站的详细信息。

答案 2 :(得分:1)

您应该使用一些mysql命令来分析您的查询,使用EXPLAIN和select语句 并检查表和索引结构。

使用命令

设置性能分析= 1;

然后使用您的选择查询 使用命令

显示query1的个人资料;

检查结果是什么东西在说多少时间。

和其他一些imp查询

* SHOW CREATE TABLE tbl \ G - 引擎,索引

  • 显示表状态'tbl'\ G - sizes

  • EXPLAIN SELECT ... \ G - 效率低下的线索

  • SHOW VARIABLES LIKE'%buffer%'; - ca **

答案 3 :(得分:0)

在两个表中索引EAN列并尝试。

也试试这个

explain (SELECT * FROM `product` WHERE EAN = '11110') UNION (SELECT * FROM `product_variants` WHERE EAN = '11110')