我有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 马特
答案 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')