【问题标题】:SQL query takes too long to run in SSMSSQL 查询在 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分享查询计划

标签: sql sql-server ssms


【解决方案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;
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-22
      • 2021-09-21
      • 1970-01-01
      • 1970-01-01
      • 2021-09-13
      • 2011-07-28
      • 2015-11-25
      相关资源
      最近更新 更多