SQL 查询在 SSMS 中运行时间过长

Posted

技术标签:

【中文标题】SQL 查询在 SSMS 中运行时间过长【英文标题】:SQL query takes too long to run in SSMS 【发布时间】:2021-03-15 12:28:54 【问题描述】:

我有以下查询,它在 Oracle 开发人员中工作得非常好

select TRIM(a.filterh) 
from CHANNEL a,GENRE b
where b.label = 'M001CL01_ABC' 
  and a.s_r_id = b.r_id 
  and a.filterh in (select c.filterh 
                    from CHANNEL c, GENRE d 
                    where d.label = 'M001AL03' and c.s_r_id = d.r_id)

我只是尝试为 SQL 开发人员简化上面的查询和一些语法更改,而下面的查询需要大量时间才能在 SSMS 中运行

select TRIM(a.filterh) 
from CHANNEL a 
inner join GENRE b on a.s_r_id = b.r_id
where b.label = 'M001CL01_ABC' 
  and a.filterh in (select c.filterh 
                    from CHANNEL c
                    inner join GENRE d on c.s_r_id = d.r_id
                    where d.label = 'M001AL03')

我只是想了解我在这里做错了什么,如何改进我的查询以及为什么 SQL 查询需要很多时间。

谢谢。

【问题讨论】:

“不”不是很具有描述性。你有错误吗?出乎意料的结果?怎么了?请注意,在这两个数据库中,可能有比这里所做的更好的方法。 @GordonLinoff 我已经更新了我的问题,你能告诉我什么是 SQL 查询的更好方法吗? 这将有助于查看表模式和现有索引。 in 子句看起来很可疑,可能只用 exists 替换 Genre 表? 我会尽快发布架构,数据以十万为单位,因此无法发布 请添加表和索引定义,也请通过brentozar.com/pastetheplan分享查询计划 【参考方案1】:

看看EXISTS而不是IN是否能更好地改善这种情况。

select TRIM(a.filterh) 
from CHANNEL a 
inner join GENRE b on a.s_r_id = b.r_id and b.label = 'M001CL01_ABC' 
where exists(select *
            from CHANNEL c
            inner join GENRE d on c.s_r_id = d.r_id and d.label = 'M001AL03'
            where a.filterh = c.filterh) 

【讨论】:

我知道Exists,但您能帮我了解一下我的查询中的a.filterh in 部分在您的版本中是如何处理的 @m_beta,它被移动到内部查询的where部分。【参考方案2】:

看起来您可能可以执行以下操作,如果没有看到数据并能够进行测试,很难确定:

select TRIM(a.filterh) 
from CHANNEL a 
inner join GENRE b on a.s_r_id = b.r_id
where b.label = 'M001CL01_ABC' 
    and exists (select * from GENRE g where g.r_id=a.s_r_id and g.label='M001AL03')

【讨论】:

【参考方案3】:

这是我的查询版本。请记住,由于没有要测试的数据,所以我无法正确测试它,所以由您检查它是否可以编译。

这里我所做的只是删除了子查询,因为它们经常导致查询优化器出错

select TRIM(a.filterh) 
  from CHANNEL a 
  join GENRE b on a.s_r_id = b.r_id
  join CHANNEL c on a.filterh = c.filterh 
  join GENRE d on c.s_r_id = d.r_id
 where b.label = 'M001CL01_ABC' 
   and d.label = 'M001AL03'

另外一点要提到的是,性能问题可能取决于很多事情。例如行数、索引、存储设备等。如果您以后发布类似的问题,最好在执行查询时向我们提供执行计划和打开的统计信息。

如果查询运行缓慢,ON A TEST INSTANCE 尝试在 channel.filterg 上创建一个索引,在genre.label 列上创建另一个索引。

【讨论】:

这个查询可以执行,只是检查是否能得到想要的输出。我会尽快回复。 @m_beta 如果以上提供的所有解决方案都不适合您,请检查我的更新答案【参考方案4】:

我认为您可以在任一数据库中使用聚合:

select TRIM(c.filterh) 
from CHANNEL c join
     GENRE g
     on g.s_r_id = c.r_id
where g.label in ('M001CL01_ABC', 'M001AL03')
group by TRIM(c.filterh)
having count(distinct g.label) = 2;

你应该学会使用有意义的表别名。 ab 等任意字母无助于任何人理解查询。

【讨论】:

以上是关于SQL 查询在 SSMS 中运行时间过长的主要内容,如果未能解决你的问题,请参考以下文章

批量 kill mysql 中运行时间长的sql

找出python程序中运行时最耗时间的部分

为啥在火花中运行时配置单元查询不起作用

Postgres 选择查询在使用 JDBC 时运行缓慢,但在从同一服务器在 PSQL 中运行时快速

为啥'get_json_object'在spark和sql工具中运行时返回不同的结果

在新进程中运行时窗口标题中的“无响应”