【问题标题】:Need tips for optimizing SQL Query using a JOIN需要使用 JOIN 优化 SQL 查询的技巧
【发布时间】:2009-03-31 03:03:43
【问题描述】:

在查看过去几天时,我正在编写的查询运行良好,一旦我过去一周,它就会爬行(约 20 分钟)。我将 3 张桌子连接在一起。我想知道我应该寻找什么东西来让它运行得更快。我真的不知道该帖子还需要哪些其他信息。

编辑:更多信息:db 是 Sybase 10。查询:

SELECT a.id, a.date, a.time, a.signal, a.noise,
b.signal_strength, b.base_id, b.firmware,
a.site, b.active, a.table_key_id
FROM adminuser.station AS a
JOIN adminuser.base AS b
ON a.id = b.base_id
WHERE a.site = 1234 AND a.date >= '2009-03-20'

我还取出了 3rd JOIN,但它仍然运行得非常慢。我应该尝试另一种 JOIN 方法吗?

【问题讨论】:

  • “超过一周”是什么意思?一周的数据而不是几天的数据?在生产中运行了一个多星期?
  • 另外,您使用的是哪个数据库服务器?微软SQL? MySQL?甲骨文?
  • 我第二次发布您的查询,我们可以提供帮助,但我们需要更多信息
  • 另外为了解决这个问题,您是否对连接条件中使用的列进行了索引,并确认在执行查询时使用了索引?

标签: sql optimization join sybase


【解决方案1】:

我不太了解 Sybase 10,但尝试运行该查询,例如 10 天,然后在一段时间内的每一天分别运行 10 次并比较时间。如果第一种情况的时间要长得多,那么您可能已经达到了数据库缓存限制。

解决方案不是简单地在循环中运行较短时间的查询(在程序中,而不是在 SQL 中)。如果表 A 按日期分区,则效果特别好。

【讨论】:

  • 实际上,这曾经是连接一个每天增长 5000 万条记录(大约 120 列)并包含一年数据的表的唯一有效方法。
【解决方案2】:

您可以通过在 SQL Server Management Studio 中使用 Include Actual Execution Plan 选项集(在 Query 菜单)。

这将向您显示 SQLServer 为执行查询而执行的步骤图 - 以及每个步骤的相对成本。

下一步是对查询稍作修改(尝试以不同的方式进行),然后同时运行新版本和旧版本。您将获得两个执行计划,其相对成本不仅针对每个步骤,而且针对查询的两个版本!因此,您可以客观地判断您是否正在取得进展。

我在调试/优化查询时一直这样做。

【讨论】:

  • 我使用的是 Sybase 10,所以不可能。
【解决方案3】:

确保您在外键上有索引。

【讨论】:

    【解决方案4】:

    这听起来更像是您的客户端代码中存在内存泄漏或没有关闭数据库连接,而不是查询有任何问题。

    [编辑]
    没关系:您的意思是查询日期范围而不是服务器处于活动状态的持续时间。我会留下这个来帮助其他人避免同样的困惑。

    此外,如果您可以发布 sql 查询,这将有所帮助,即使您需要先对其进行一些混淆,并且最好检查您的日期列上是否有索引以及较长返回的记录数范围。

    【讨论】:

    • 我必须明天发布。我正在家里尝试阅读它。
    【解决方案5】:

    如果您的数据库支持,您可能需要考虑使用 PARTITION 作为日期范围。我听说这有很大帮助。

    【讨论】:

      【解决方案6】:

      阅读“Professional SQL Server 2005 Performance Tuning”一书,它非常棒。

      【讨论】:

      • 我们不能使用 Sybase 10
      【解决方案7】:

      你没有提到你的数据库。如果不是 SQL Server,如何获取数据的细节可能会有所不同,但建议基本相同。

      当然,看看索引,但首先要做的是遵循 Blorgbeard 的建议并使用 Management Studio 扫描执行计划(同样,如果您正在运行 SQL Server)。

      我猜你会看到,对于小的日期范围,优化器会选择一个合理的查询计划,但是当日期范围很大时,它会选择完全不同的东西,可能涉及表扫描或索引扫描,以及可能导致非常大的临时记录集的连接。执行计划分析器将揭示所有这些。

      扫描意味着优化器认为对整个表或整个索引进行打磨比寻找特定值更便宜。

      您最终想要做的是获取索引并设置查询的语法,以便您在查询的查询计划中保留索引搜索,无论日期范围如何,或者如果失败,您需要的扫描是过滤以及您可以设法最小化临时记录集大小,从而避免过多的读取和 I/O。

      【讨论】:

      • 正在索引正确的列,我使用的是 Sybase 10。
      【解决方案8】:
      SELECT
      
       a.id, a.date, a.time, a.signal, a.noise,a.site, b.active, a.table_key_id,
       b.signal_strength, b.base_id, b.firmware
      
      FROM 
      
      ( SELECT * FROM adminuser.station 
            WHERE site = 1234 AND date >= '2009-03-20') AS a
      JOIN 
      
          adminuser.base AS b
      ON
      
          a.id = b.base_id
      

      有点重写查询,以便首先过滤所需的行然后执行连接,而不是执行连接然后过滤结果。

      您可以只选择所需的列,而不是从子查询中提取 *,这可能没什么帮助。

      这可能对加快速度没什么帮助。

      虽然这在 MySql 中有效,但我不确定 sysbase 语法。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-10
        • 2013-07-31
        • 2019-03-30
        • 2021-05-18
        • 2015-01-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多