我经常读到,当必须检查一行是否存在时,应该始终使用 EXISTS 而不是 COUNT 来完成。
然而,在最近的几个场景中,我测量了使用计数时的性能改进。
模式是这样的:
LEFT JOIN (
SELECT
someID
, COUNT(*)
FROM someTable
GROUP BY someID
) AS Alias ON (
Alias.someID = mainTable.ID
)
Run Code Online (Sandbox Code Playgroud)
我不熟悉判断 SQL Server“内部”发生了什么的方法,所以我想知道 EXISTS 是否存在一个未知的缺陷,这对我所做的测量非常有意义(EXISTS 可能是 RBAR 吗?!)。
你对这种现象有什么解释吗?
编辑:
这是您可以运行的完整脚本:
SET NOCOUNT ON
SET STATISTICS IO OFF
DECLARE @tmp1 TABLE (
ID INT UNIQUE
)
DECLARE @tmp2 TABLE (
ID INT
, X INT IDENTITY
, UNIQUE (ID, X)
)
; WITH T(n) AS (
SELECT
ROW_NUMBER() OVER (ORDER …Run Code Online (Sandbox Code Playgroud) 背景
我有一个针对 SQL Server 2008 R2 运行的查询,该查询连接和/或左连接大约 12 个不同的“表”。该数据库相当大,有超过 5000 万行的许多表和大约 300 个不同的表。这是一家在全国拥有 10 个仓库的大型公司。所有的仓库都对数据库进行读写。所以它很大而且很忙。
我遇到问题的查询如下所示:
select t1.something, t2.something, etc.
from Table1 t1
inner join Table2 t2 on t1.id = t2.t1id
left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
[etc]...
where t1.something = 123
Run Code Online (Sandbox Code Playgroud)
请注意,其中一个连接位于不相关的子查询上。
问题是从今天早上开始,没有对系统进行任何更改(我或我团队中的任何人都知道),通常需要大约 2 分钟才能运行的查询,开始需要一个半小时才能运行——当它跑了。数据库的其余部分运行良好。我已经从它通常运行的 sproc 中取出了这个查询,并且我已经在 SSMS 中以相同的速度在带有硬编码参数变量的情况下运行它。
奇怪的是,当我将不相关的子查询放入临时表中,然后使用它而不是子查询时,查询运行良好。另外(这对我来说是最奇怪的)如果我将这段代码添加到查询的末尾,查询运行得很好:
and t.name like '%'
Run Code Online (Sandbox Code Playgroud)
我从这些小实验中得出结论(可能是错误的),速度变慢的原因是 SQL 的缓存执行计划是如何设置的——当查询有点不同时,它必须创建一个新的执行计划。
我的问题是:当一个曾经运行得很快的查询在半夜突然开始运行缓慢并且除了这个查询之外没有其他任何影响时,我该如何解决它以及如何防止它在未来发生? 我怎么知道 SQL 在内部做了什么使其如此缓慢(如果错误的查询运行,我可以获得它的执行计划但它不会运行——也许预期的执行计划会给我一些东西?)?如果这个问题与执行计划有关,我如何让 SQL 不认为真正糟糕的执行计划是个好主意?
此外,这不是参数嗅探的问题。我以前见过,但事实并非如此,因为即使我在 SSMS 中对变量进行硬编码,我的性能仍然很慢。
我遇到了一个奇怪的问题,SQL Server 2016 标准版 64 位似乎将自己限制在分配给它的总内存的一半(128GB 中的 64GB)。
的输出@@VERSION是:
Microsoft SQL Server 2016 (SP1-CU7-GDR) (KB4057119) - 13.0.4466.4 (X64) 2017 年 12 月 22 日 11:25:00 版权所有 (c) Windows Server 2012 R2 Datacenter 6.3 上的 Microsoft Corporation 标准版(64 位)(内部版本 9600:)(管理程序)
的输出sys.dm_os_process_memory是:
当我查询时sys.dm_os_performance_counters,我看到Target Server Memory (KB)是在131072000和Total Server Memory (KB)是 at 的一半以下65308016。在大多数情况下,我认为这是正常行为,因为 SQL Server 尚未确定它需要为自己分配更多内存。
然而,它已经“卡住”在 64GB 左右超过 2 个月了。在此期间,我们对一些数据库执行了大量内存密集型操作,并向实例添加了近 40 个数据库。我们总共有 292 个数据库,每个数据库都有 4GB 的预分配数据文件和 256MB 的自动增长速率和 2GB …
我们使用的是 PostgreSQL v8.2.3。
涉及的表有:EMPLOYEE和EMAILLIST。
Table 1: EMPLOYEE (column1, column2, email1, email2, column5, column6)
Table 2: EMAILLIST (email)
Run Code Online (Sandbox Code Playgroud)
2 个表以这样的方式连接,如果 EMPLOYEE.EMAIL1 或 EMPLOYEE.EMAIL2 没有匹配的条目,则将返回这些行。
SELECT employee.email1, employee.email2,
e1.email IS NOT NULL AS email1_matched, e2.email IS NOT NULL AS email2_matched
FROM employee
LEFT JOIN emaillist e1 ON e1.email = employee.email1
LEFT JOIN emaillist e2 ON e2.email = employee.email2
WHERE e1.email IS NULL OR e2.email IS NULL
Run Code Online (Sandbox Code Playgroud)
列EMAIL是VARCHAR(256)的EMAILLIST表索引。现在,响应时间是 14 秒。
表数统计:目前EMPLOYEE有165,018条记录,EMAILLIST有1,810,228条记录,未来两个表都有望增长。
使用 SQL Server 2005。
我正在执行一个没有 where 子句的巨大 DELETE FROM。它基本上等同于 TRUNCATE TABLE 语句 - 除了我不允许使用 TRUNCATE。问题是表很大 - 1000 万行,需要一个多小时才能完成。有没有办法让它更快,没有:
t-log 已经在一个单独的磁盘上。
欢迎任何建议!
RAM 的重要性是一个既定的事实,但在 MySQL 使用 CPU 时,关于内核和多线程重要性的资料要少得多。我说的是在 4cores vs 6cores vs 8cores 上运行 MySQL 的区别等等。
不同的存储引擎使用 CPU 的方式不同吗?
我注意到查询子句中的USING构造(而不是ON)可能会在某些情况下引入优化障碍。FROMSELECT
我的意思是这个关键词:
选择 * 从一个 加入 b使用(a_id)
只是在更复杂的情况下。
上下文:this comment to this question。
我用这个了很多,从来没有发现过这么远。我会对展示效果的测试用例或任何指向更多信息的链接非常感兴趣。我的搜索努力是空的。
完美的答案将是一个测试用例,USING (a_id)与替代 join 子句相比,它的性能较差ON a.a_id = b.a_id——如果这真的可以发生的话。
在每个 SQL 语句之后使用 GO 语句的原因是什么?我知道 GO 表示批处理结束和/或允许声明的声誉,但是在每个声明之后使用它有什么好处。
我只是很好奇,因为很多 Microsoft 文档等都在每次声明后开始使用它,或者我才刚刚开始注意到。
还有什么被认为是最佳实践?
我有一个旧模式(免责声明!),它使用基于哈希生成的 id 作为所有表的主键(有很多)。这种 id 的一个例子是:
922475bb-ad93-43ee-9487-d2671b886479
Run Code Online (Sandbox Code Playgroud)
改变这种方法是不可能的,但是索引访问的性能很差。撇开这可能的无数原因不谈,我注意到有一件事似乎不太理想 - 尽管所有许多表中的所有 id 值的长度都正好是 36 个字符,但列类型是varchar(36),而不是 char(36)。
将列类型更改为固定长度是否会char(36)提供任何显着的索引性能优势,除了每个索引页的条目数量增加很小等之外?
即在处理固定长度类型时 postgres 的执行速度是否比处理可变长度类型快得多?
请不要提及微小的存储节省 - 与对列进行更改所需的手术相比,这无关紧要。
我有一个与性能相关的问题。假设我有一个名为 Michael 的用户。进行以下查询:
UPDATE users
SET first_name = 'Michael'
WHERE users.id = 123
Run Code Online (Sandbox Code Playgroud)
查询是否会实际执行更新,即使它被更新为相同的值?如果是这样,我该如何防止它发生?
performance ×10
sql-server ×5
postgresql ×4
index ×2
delete ×1
join ×1
memory ×1
mysql ×1
optimization ×1
query ×1
select ×1
sp-blitz ×1
t-sql ×1
update ×1
varchar ×1