优化 MySQL NOT IN( 查询
Posted
技术标签:
【中文标题】优化 MySQL NOT IN( 查询【英文标题】:Optimizing a MySQL NOT IN( query 【发布时间】:2017-10-15 00:48:06 【问题描述】:我正在尝试优化这个 mysql 查询。我想计算在查看当前预约之前没有预约的客户数量。换句话说,如果他们有约会(这是 NOT IN( 子查询正在检查的内容),则排除他们。
但是,这个查询绝对会影响性能。我知道 MySQL 在 NOT IN( 查询方面不是很好,但我不确定优化此查询的最佳方法。运行需要 15 到 30 秒。我在 CustNo、AptStatus、和 AptNum。
SELECT
COUNT(*) AS NumOfCustomersWithPriorAppointment,
FROM
transaction_log AS tl
LEFT JOIN
appointment AS a
ON
a.AptNum = tl.AptNum
INNER JOIN
customer AS c
ON
c.CustNo = tl.CustNo
WHERE
a.AptStatus IN (2)
AND a.CustNo NOT IN
(
SELECT
a2.CustNo
FROM
appointment a2
WHERE
a2.AptDateTime < a.AptDateTime)
AND a.AptDateTime > BEGIN_QUERY_DATE
AND a.AptDateTime < END_QUERY_DATE
提前谢谢你。
【问题讨论】:
请为查询中的每个表提供SHOW CREATE TABLE
语句。
BEGIN_QUERY_DATE
是常量吗?还是另一列?使用LEFT JOIN .. IS NULL
重写查询;告诉我们它是否更快。
顺便说一下,你的外连接(a)实际上是一个内连接
【参考方案1】:
尝试以下方法:
SELECT
COUNT(*) AS NumOfCustomersWithPriorAppointment,
FROM
transaction_log AS tl
INNER JOIN
appointment AS a
ON
a.AptNum = tl.AptNum
LEFT OUTER JOIN appointment AS earlier_a
ON earlier_a.CustNo = a.CustNo
AND earlier_a.AptDateTime < a.AptDateTime
INNER JOIN
customer AS c
ON
c.CustNo = tl.CustNo
WHERE
a.AptStatus IN (2)
AND earlier_a.AptNum IS NULL
AND a.AptDateTime > BEGIN_QUERY_DATE
AND a.AptDateTime < END_QUERY_DATE
这将受益于(CustNo,AptDateTime)
上的复合索引。如果它适合您的业务模型,请使其独一无二(从逻辑上看应该,但实际上可能并非如此,这取决于您如何处理应用程序中的冲突。)
如果这不能产生足够的性能改进,请为所有表提供SHOW CREATE TABLE
语句。
【讨论】:
这个查询准确无误。非常感谢您的帮助和建议!以上是关于优化 MySQL NOT IN( 查询的主要内容,如果未能解决你的问题,请参考以下文章