我正在尝试优化查询。表中有三种不同的查找,我认为这些查找不是必需的。
这是原始查询,我想优化。
SELECT DISTINCT(productid) FROM q_products
WHERE visibility=1 and status=0 AND productid IN (productidList)
UNION ALL
SELECT DISTINCT(q_products.productid) FROM q_products,q_product_apply_access
WHERE q_products.productid=q_product_apply_access.productid
AND q_product_apply_access.partnerid='partnerid'
AND q_product_apply_access.apply_status=0
AND q_products.visibility=3 AND q_products.status=0
AND q_products.productid IN (productidList)
UNION ALL
SELECT DISTINCT(q_products.productid) FROM q_products,q_product_aff_access
WHERE q_products.productid=q_product_aff_access.productid
AND q_product_aff_access.accid='accountid'
AND q_products.visibility=2 AND q_products.status=0
AND q_products.productid IN (productidList)
让我带你完成这个问题,
1)我从productid
选择了q_products
和visibility=1
并且同样位于status=0
productidList
2)我现在从productid
中选择不同的q_products
并检查另一个表productid
中是否存在相同的q_product_apply_access
,如果是,则检查{{1} }}与我们相同,如果q_product_apply_access.partnerid
为0,则再次检查q_product_apply_access.apply_status
是否在productid
中。
3)它会执行类似的操作,如果productidList
位于productid
,则会再次检查。
我的优化想法是按照以下方式执行 - >
1)从我的productidList中的productidList
中选择所有productids
。
2)检查这些q_products
是否在表productids
和q_product_apply_access
中,如果是,则表示其后续条件已满足。
3)完成所有这些后,我会检查其中哪一个有q_product_aff_access
和q_products.visibility IN (1,2,3)
。
我认为通过这种方式,我可以最小化表中的查找,并且我的查询将在productidList的最小子集中查询,该子集最多可包含20-30行。
这是我的代码,但我没有得到正确的答案。有人能告诉我怎么做吗?或者我应该如何在这里应用嵌套循环?
q_products.status=0
答案 0 :(得分:1)
你问题的标题:
使用" AND"和"或"在SQL查询中
可能更准确地定义为:
将使用" AND"和/或" OR"语句可以帮助这个查询更快地运行吗?
而简短的回答是,否 .--优化可能需要在其他地方完成。
所以,答案很长:
经过一段时间的观察,这些要求已经成为'原始查询阻止逻辑JOIN
加速任何事情。让它运行得更快的最好方法是利用被引用的表上的索引。我原来的答案是使用内部选择,但没有达到要求。通过要求,我的意思是必须从满足三个不同和不同标准的产品表中返回唯一产品列表。
也就是说,我会将原始查询重写为更具可读性的内容,使用JOIN
语句和别名来提高可读性(注意缺少DISTINCT
- {{1}确保所有3个结果集中的唯一记录:
UNION
因此,您遇到的问题有点困难,因为首先我很难绕过原始查询。也就是说,我使用内部选择作为SELECT p.productid
FROM q_products p
WHERE visibility = 1
AND status = 0
AND productid IN (productIdList)
UNION
SELECT p.productid
FROM q_products p
JOIN q_product_apply_access paa ON paa.productid = p.productid
WHERE paa.partnerid = 'partnerid'
AND paa.apply_status = 0
AND p.visibility = 3
AND p.status = 0
AND p.productid IN (productidList)
UNION
SELECT p.productid
FROM q_products p
JOIN q_product_aff_access paf ON paf.productid = p.productid
WHERE paf.accid = 'accountid'
AND p.visibility = 2
AND p.status = 0
AND p.productid IN (productidList)
表的连接,将可能的解决方案汇集在一起。我还没有测试过,所以让我知道结果如何:
q_products
答案 1 :(得分:0)
INDEX(visibility, status, productid)
使用原始UNION ALL
请提供SHOW CREATE TABLE
;这可能会促使其他技术。
(编辑)
事实之后,你可以做到
ALTER TABLE q_products ADD INDEX(visibility, status, productid);
这需要一些时间,具体取决于桌子的大小。
INDEX通常比表格本身小得多。
索引是您防止慢查询的第一道防线。 (重写是第二个。)
q_products有多大?
答案 2 :(得分:0)
稍微重新格式化的原始查询是:
SELECT DISTINCT(q_products.productid)
FROM q_products
WHERE q_products.visibility = 1
AND q_products.status = 0
AND q_products.productid IN (productidList)
UNION ALL
SELECT DISTINCT(q_products.productid)
FROM q_products, q_product_apply_access
WHERE q_products.productid = q_product_apply_access.productid
AND q_product_apply_access.partnerid = 'partnerid'
AND q_product_apply_access.apply_status = 0
AND q_products.visibility = 3
AND q_products.status = 0
AND q_products.productid IN (productidList)
UNION ALL
SELECT DISTINCT(q_products.productid)
FROM q_products, q_product_aff_access
WHERE q_products.productid = q_product_aff_access.productid
AND q_product_aff_access.accid = 'accountid'
AND q_products.visibility = 2
AND q_products.status = 0
AND q_products.productid IN (productidList)
您没有告诉我们除了visibility
,1
,2
以外3
是否还有其他值,所以我们必须假设可以其他值(但请注意此答案下方的评论)。
我们可以看到有一些常见的子表达式限制来自q_products
(status = 0
和productid IN (productidList)
的行,其中并不清楚productidList
真正的WITH pv AS
(SELECT productid, visibility
FROM q_products
WHERE status = 0
AND visibility IN (1, 2, 3) -- or visibility >= 1 and visibility <= 3
AND productid IN (productidList)
)
SELECT pv.productid
FROM pv
WHERE pv.visibility = 1
UNION ALL
SELECT DISTINCT(pv.productid)
FROM pv
JOIN q_product_apply_access AS a
ON pv.productid = a.productid
WHERE pv.visibility = 3
AND a.apply_status = 0
AND a.partnerid = 'partnerid'
UNION ALL
SELECT DISTINCT(pv.productid)
FROM pv
JOIN q_product_aff_access AS f
ON pv.productiond = f.productid
WHERE pv.visibility = 2
AND f.accid = 'accountid'
是的,但我们可以假设它运作正常。
如果MySQL支持CTE(常用表表达式,又名WITH子句),那将非常有用:
visibility
由于MySQL还不支持CTE,因此您可能需要逐字写入CTE 3次,并希望优化器能够发现您正在做的事情。或者,由于所有备选方案都要更精确地过滤可见性,因此您可以将该术语包含在CTE的修改形式中(并避免明确选择SELECT pv.productid
FROM (SELECT productid
FROM q_products
WHERE status = 0
AND visibility = 1
AND productid IN (productidList)
) AS pv
UNION ALL
SELECT DISTINCT(pv.productid)
FROM (SELECT productid
FROM q_products
WHERE status = 0
AND visibility = 3
AND productid IN (productidList)
) AS pv
JOIN q_product_apply_access AS a
ON pv.productid = a.productid
WHERE a.apply_status = 0
AND a.partnerid = 'partnerid'
UNION ALL
SELECT DISTINCT(pv.productid)
FROM (SELECT productid
FROM q_products
WHERE status = 0
AND visibility = 2
AND productid IN (productidList)
) AS pv
JOIN q_product_aff_access AS f
ON pv.productiond = f.productid
WHERE f.accid = 'accountid'
)并将其写出三次 - 如下所示:
q_products
这应该产生相同的结果。很难确定它会更快。这可能取决于{{1}}的状态和可见性列是否有合适的索引。 UNION的第一个术语可以更简单地编写,但是这个表示与其他两个替代方案是统一的,这往往会使这些事情更清晰(对于人类阅读查询,也可能对查询优化器也是如此)。
与往常一样,研究实际的查询计划可能会帮助您改进。