因此,此查询目前在网上商店中用于检索有关文章的技术数据。 它的目的很好,除了最近显示的产品数量增加,导致某些类别的长时间加载时间不可接受。
对于其中一个最糟糕的页面,这个(以及其他一些查询)被请求约80次。
我最近才知道MySQL没有优化没有依赖参数的子查询只运行一次。
因此,如果有人可以帮助我解决其中一个问题并解释如何替换in和存在加入,我可能会自己更改其他查询。
select distinct criteria.cri_id, des_texts.tex_text, article_criteria.acr_value, article_criteria.acr_kv_des_id
from article_criteria, designations, des_texts, criteria, articles
where article_criteria.acr_cri_id = criteria.cri_id
and article_criteria.acr_art_id = articles.art_id
and articles.art_deliverystatus = 1
and criteria.cri_des_id = designations.des_id
and designations.des_lng_id = 9
and designations.des_tex_id = des_texts.tex_id
and criteria.cri_id = 328
and article_criteria.acr_art_id IN (Select distinct link_art.la_art_id
from link_art, link_la_typ
where link_art.la_id = link_la_typ.lat_la_id
and link_la_typ.lat_typ_id = 17484
and link_art.la_ga_id IN (Select distinct link_ga_str.lgs_ga_id
from link_ga_str, search_tree
where link_ga_str.lgs_str_id = search_tree.str_id
and search_tree.str_type = 1
and search_tree.str_id = 10132
and EXISTS (Select *
from link_la_typ
where link_la_typ.lat_typ_id = 17484
and link_ga_str.lgs_ga_id = link_la_typ.lat_ga_id)))
order by article_criteria.acr_value
我认为这是次要子查询的主要问题
我只是注意到我可以移除最后存在但仍然得到相同的结果但没有增加速度,但不是问题的一部分;)我会弄清楚自己是否仍然需要那部分。
如果我遗漏了一些有用的信息,那么任何帮助或指示都会受到赞赏。
答案 0 :(得分:1)
我认为这是等效的:
SELECT DISTINCT c.cri_id, dt.tex_text, ac.acr_value, ac.acr_kv_des_id
FROM article_criteria AS ac
JOIN criteria AS c ON ac.acr_cri_id = c.cri_id
JOIN articles AS a ON ac.acr_art_id = a.art_id
JOIN designations AS d ON c.cri_des_id = d.des_id
JOIN des_texts AS dt ON dt.tex_id = d.des_tex_id
JOIN (SELECT distinct la.la_art_id
FROM link_art AS la
JOIN link_la_typ AS llt ON la.la_id = llt.lat_la_id
JOIN (SELECT DISTINCT lgs.lgs_ga_id
FROM link_ga_str AS lgs
JOIN search_tree AS st ON lgs.lgs_str_id = st.str_id
JOIN link_la_typ AS llt ON lgs.lgs_ga_id = llt.lat_ga_id
WHERE st.str_type = 1
AND st.str_id = 10132
AND llt.lat_typ_id = 17484) AS lgs
ON la.la_ga_id = lgs.lgs_ga_id
WHERE llt.lat_typ_id = 17484) AS la
ON ac.acr_art_id = la.la_art_id
WHERE a.art_deliverystatus = 1
AND d.des_lng_id = 9
AND c.cri_id = 328
ORDER BY ac.acr_value
所有IN <subquery>
子句都可以替换为JOIN <subquery>
,然后您在测试的列上JOIN
等于子查询返回的列。并且EXISTS
测试将转换为与表的连接,将子查询的WHERE
子句中的比较移动到ON
的{{1}}子句中。< / p>
可能有可能将整个事物弄平,而不是加入子查询。但我怀疑性能会很差,因为这不会使用JOIN
来减少临时表。因此,您在产生的交叉产品中会发生组合爆炸,最后必须在顶部DISTINCT
处减少。
我已将所有隐式连接转换为ANSI DISTINCT
子句,以使结构更清晰,并添加了表别名以使事物更具可读性。
答案 1 :(得分:0)
通常,您可以将FROM tab1 WHERE ... val IN (SELECT blah)
转换为此类连接。
FROM tab1
JOIN (
SELECT tab1_id
FROM tab2
JOIN tab3 ON whatever = whatever
WHERE whatever
) AS sub1 ON tab1.id = sub1.tab1_id
JOIN
(内部联接)会删除与您的查询中的ON条件不匹配的行。
如果您的tab1_id
值可能与内部查询重复,请使用SELECT DISTINCT
。但除非你需要,否则不要使用SELECT DISTINCT
;评估成本很高。