我有2张表加入: "产品"表,此表包含257613行 这是结构:
id int(11) primary key autoincrement
id_category varchar(100)
name_category varchar(500)
name varchar(1000)
name_translated varchar(1000)
reference varchar(100)
link varchar(1000)
original_price varchar(45)
resell_price varchar(45)
active int(11)
ean varchar(16)
json_detail text
date_add date
date_update date
" stores_product"表,此表包含181142行 这是结构:
id int(11) primary key autoincrement
reference varchar(128)
id_product int(11)
id_image_product int(11)
id_stock_product
id_store int(11)
这是有罪的慢速查询:
SELECT * FROM product AS p
LEFT JOIN stores_product AS sp ON p.reference = sp.reference
WHERE sp.id_store = 3
此查询没有得到我的回复,我在35分钟后阻止执行而没有结果。 要处理的行太多?或者我在查询中出错?
答案 0 :(得分:1)
有几点需要注意:
当您在连接字段(在您的情况下为sp.id_store = 3
)上具有非空条件时,执行外连接没有任何好处。由于外连接比内连接更昂贵,因此在这种情况下使用后者:inner join
。结果是一样的,但可能更快。
另一方面,如果您希望通过外部联接列出所有产品,则您的查询不正确。然后,您必须将条件从where
子句移到on
子句中,如下所示:
LEFT JOIN stores_product AS sp
ON p.reference = sp.reference
AND sp.id_store = 3
连接条件看起来不像预期的那样。通常,您会期望sp.id_product = p.id
。但在评论中你解释这两个领域是无关的。这是一种非常令人困惑的命名方式。您应该考虑在product
表中存储引用主键的外键。
根据数据的分布方式,您将从以下两个索引之一中获益 - 您需要创建这些索引: stores_product(id_store,reference)或 stores_product(reference,id_store)。
显然 product(id)应该是主键。
创建缺失的索引,并使用explain select ...
查看执行计划,看看实际使用的是什么。
答案 1 :(得分:0)
好吧,既然你加入257613行和181142行,那只需要时间。 查询很好,我担心除了升级mysql-server之外你无法真正提高性能。 尽管数据量很大,35分钟似乎非常长。
您可能还想添加主键,索引和缓存:
答案 2 :(得分:0)
索引是你的表现救星;使用它们。
SELECT * FROM product AS p
LEFT JOIN stores_product AS sp
ON p.reference = sp.reference -- `p` needs INDEX(reference)
WHERE sp.id_store = 3 -- Needs INDEX(id_store)
但还有更多......
您对reference
的定义不一致;解决这个问题。
删除LEFT
;你没有真正做LEFT JOIN
,因为你指的是sp.id_store
。如果从那里开始,查询将运行得更快。
SELECT *
从两个表中获取所有列;这似乎有点矫枉过正。
重新考虑您的许多id
列。似乎比你需要的更多。
如果reference
确实是product
的唯一标识符,请将其设为PRIMARY KEY
并删除id
。
答案 3 :(得分:0)
知道索引可能会导致行更新或在表中插入时出现问题。我建议使用临时表。到目前为止(据我所知),它们是减少计时成本而不更改数据库配置中任何内容的最佳方法。在最后删除临时表始终是一种更好的做法。
对于上述问题。它可能是一个包含以下内容的存储过程:
select reference, (the columns you need or just *)
INTO #TempTable
from stores_product sp
where sp.id_store = 3
Select *
from product AS p
left join #TempTable sp ON p.reference = sp.reference
Drop table #TempTable
答案 4 :(得分:0)
关于MySQL JOINS,
编写JOINS
时,请确保
CHARSET(latin1, utf8)
是相同的。即。被联接的表应具有相同的CHARSET类型。可以通过SHOW CREATE TABLE <table_name>
varchar, int..
)(在ON
条件下使用)。varchar(50)
varchar(50)
的加入速度将比varchar(50)
和varchar(100)
注意:如果Joins或按要求进行的任何查询花费时间,请始终使用EXPLAIN
检查正在使用的索引以及不同的统计信息以了解执行计划。