让我们有一个支付表,其中包含 35 列,主键 (autoinc bigint) 和 3 个非聚集、非唯一索引(每个在一个 int 列上)。
在表的列中,我们有两个日期时间字段:
付款日期
datetime NOT NULL
编辑日期
datetime NULL
该表有大约 1 200 000 行。只有 ~1000 行的 edit_date 列 = null。9000 行的 edit_date 不为 null 且不等于 payment_date 其他有 edit_date=payment_date
当我们运行以下查询 1时:
select top 1 *
from payments
where edit_date is not null and (payment_date=edit_date or payment_date<>edit_date)
order by payment_date desc
服务器需要几秒钟来完成它。但是如果我们运行查询 2:
select top 1 *
from payments
where edit_date is not null
order by payment_date desc
执行结束时数据库“tempdb”的日志文件已满。备份数据库的事务日志以释放一些日志空间。
如果我们将 * 替换为某个特定的列,请参见查询 3
select top 1 payment_date
from payments
where edit_date is not null
order by payment_date desc
它也在几秒钟内完成。
魔法在哪里?
编辑 我更改了查询 1,使其在与第二个查询完全相同的行数上运行。它仍然会在一秒钟内返回,而查询 2 会填充 tempdb。
回答 我按照建议添加索引,对两个日期字段都这样做了 - 正如预期的那样,一切都开始快速工作。不过,问题是 - 为什么在这种确切情况下 sql server 在类似查询(查询 1 与查询 2)上表现不同;我想了解服务器优化的逻辑。如果两个查询确实使用了类似的 tempdb,我会同意,但他们没有....
最后,我将第一个标记为答案,在那里我看到了我的问题的必然症状,以及第一个关于如何避免这种情况的想法(即 indeces)