2

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

产品:
ID | 是大师 | EAN | 姓名 | 价格 ...

Product_Variants:
ID | PID(Product.ID 上的 FK)| 是大师 | 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

4 回答 4

2

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

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

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

无索引 = 慢速选择查询。

于 2013-07-22T09:13:55.860 回答
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)。

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

于 2013-07-22T09:20:46.340 回答
1

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

使用命令

设置分析=1;

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

显示查询 1 的配置文件;

检查结果哪个东西正在谈论多少时间。

和其他一些 imp 查询是

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

  • 显示表状态,如 'tbl'\G -- 大小

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

  • 显示变量,如 '%buffer%'; -- 约**

于 2013-07-22T09:24:28.410 回答
0

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

也试试这个

explain (SELECT * FROM `product` WHERE EAN = '11110') UNION (SELECT * FROM `product_variants` WHERE EAN = '11110')
于 2013-07-22T09:21:36.227 回答