我有2个表加入:“product”表,这个表包含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分钟后阻止了执行而没有结果。要处理的行太多?或者我在查询中出错?
关于这一点有几点需要注意:
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
表中存储引用主键的外键。创建缺少的索引,并使用explain select ...
查看执行计划,并查看实际使用的是什么。
好吧,既然你加入257613行和181142行,那只需要时间。查询很好,我担心除了升级mysql-server之外你无法真正提高性能。尽管数据量很大,35分钟似乎非常长。
您可能还想添加主键,索引和缓存:
索引是你的表现救星;使用它们。
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
。
知道索引可能导致行更新或插入表中的问题。我建议使用临时表。到目前为止(我知道)它们是在不更改数据库配置中的任何内容的情况下降低计时成本的最佳方法。最后删除临时表总是更好的做法。
所以对于上面的问题。它可以是包含以下内容的存储过程:
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