【问题标题】:MS Access 2010 SQL Top N query by group performance issue (continued)MS Access 2010 SQL Top N 查询按组性能问题(续)
【发布时间】:2014-04-22 15:27:12
【问题描述】:

我在 MS Access 2010 中遇到了严重的性能问题(直至超时),查询如下。表 TempTableAnalysis 包含 10'000-15'000 条记录。我已经收到了来自该论坛的意见,以使用前 10 名查询中的临时表 (MS Access 2010 SQL Top N query by group performance issue)

谁能解释一下如何在子查询中实现临时表以及如何加入它?我无法让它工作。

我们非常感谢任何其他提高性能的建议。

这是我的查询:

SELECT 
t2.Loc, 
t2.ABCByPick, 
t2.Planner, 
t2.DmdUnit, 
ROUND(t2.MASE,2) AS MASE, 
ROUND(t2.AFAR,2) AS AFAR

FROM TempTableAnalysis AS t2

WHERE t2.MASE IN  (
SELECT TOP 10 t1.MASE 
FROM TempTableAnalysis AS t1
WHERE t1.ABCByPick = t2.ABCByPick
ORDER BY t1.MASE DESC
)
ORDER BY
t2.ABCByPick, 
t2.MASE DESC;

【问题讨论】:

  • 你想做什么?您的性能问题可能来自您在 where 子句中进行选择的事实。每次进行比较时,您也在进行选择。因此,如果您有 1000 行,那么您将在比较的基础上进行一千次选择。您应该尝试重构您的查询,以便使用联接。如果您能解释您的问题,我可以尝试为您提供更多帮助。表名/列很难弄清楚你在做什么。
  • 乍一看,我可以告诉你一个 SQL IN-List(即以:WHERE t2.MASE IN ( SELECT TOP 10 t1.MASE FROM Temp... 开头的部分)通常被解释为一个很长的 SQL 字符串 ORstatements .即使在 Oracle 数据库上,集合大小超过几千的 IN-List 有时也会出现性能问题。如果您的内部查询(IN-list 集)与最外层集相比足够大,则连接可能更合适或至少值得一试。
  • 这里解释一下字段:loc = 仓库,ABCByPick = 产品属性,planner = 产品负责人,dmdunit = 产品零件号,MASE = 产品质量因素(AFAR不相关)。属性 ABCByPick 可以具有从 A 到 F 的值。通过第一个查询,我想通过 ABCByPick 获得前 10 个 MASE。通过第二个查询,我想通过 ABCByPick 和规划器获得前 10 个 MASE(即规划器 1 可能有 ABCByPick = A、B、C 的产品)。我还没有弄清楚如何使用连接来做到这一点,因为所有数据都在一个表中。
  • 感谢您的解释。我发布的解决方案解决了原始查询,即ABCByPick 问题。您看起来像是在塑造一套查询结果,这些结果实际上是跨不同维度和分组值的枢轴。看看你是否可以解决其中的性能问题,然后继续讨论如何提供不同的变体。

标签: sql performance ms-access-2010


【解决方案1】:

优化大型数据集的访问查询性能

根据您发布的 SQL 查询,您可以使用一些选项来优化和加快性能。

SELECT 
   t2.Loc, 
   t2.ABCByPick, 
   t2.Planner, 
   t2.DmdUnit, 
   ROUND(t2.MASE,2) AS MASE, 
   ROUND(t2.AFAR,2) AS AFAR

   FROM TempTableAnalysis AS t2
   ...

这是TempTableAnalysis 是多万条记录子查询的第一部分。如果您想从使用此“临时”表中获得更多性能,请不要将其用作动态查询(即每次打开查询时按需计算),尝试构建一个宏来推送输出到静态表:

将子查询数据附加到静态表:

  1. 创建一个QUERY 对象并将其类型更改为DELETE。将其设计为删除“临时”表对象的内容。如果您更喜欢使用 SQL,该命令将如下所示:

    DELETE My_Table.*
    FROM My_Table;
    
  2. 创建一个QUERY 对象并将其类型更改为APPEND。将其设计为查询此 OP 的 SQL 语句定义的查询中的所有字段。同样,此任务的 SQL 版本具有以下语法:

    INSERT INTO StaticAnalysisTable ( ID, Loc, Item, AvgOfScaledError )
    SELECT t1.ID, t1.Loc, t1.Item, t1.AvgOfScaledError
      FROM TempTableAnalysis as t1;
    

    下一步是自动填充此静态表,这是可选的。然而,这很简单,并且您不太可能犯错误,忘记“刷新”并在静态表有陈旧数据时访问它......导致结果不准确。

  3. 创建一个包含两个步骤的宏。每个步骤将具有以下定义:OPEN QUERY。当系统提示您打开查询时,请按以下顺序(重要)引用您在前两个步骤中创建的对象:(1) DELETE Query: (your delete query name) 然后 (2) APPEND Query: (your append query name)

SQL 查询评论和建议

已发布的 SQL 查询的以下部分可能需要一些帮助:

...

WHERE t2.MASE IN  (

     SELECT TOP 10 t1.MASE 
     FROM TempTableAnalysis AS t1
     WHERE t1.ABCByPick = t2.ABCByPick
     ORDER BY t1.MASE DESC
     )

ORDER BY
   t2.ABCByPick, 
   t2.MASE DESC;
  1. 在生成 TOP-10 数据的子查询和将这些结果与补充 MASE 表数据相关联的最外层查询之间存在一个连接。如果TempTableAnalysis.MASE 表示键值,则不需要这样做。

  2. ORDER BY

    在最里面的查询不是必需的,除非它旨在强制某种选择标准(如使用 SQL 分析函数时),这看起来不像是其中一种情况。从大型数据集中排序记录也是一种浪费 CPU 和内存的方法。

编辑:作为一个反驳论点,在 TOP N 查询旁边使用的 ORDER BY 子句实际上是有目的的,但我仍然不清楚是否有必要。为了结束讨论,另一个 SO 线程谈到了 How to Select Top 10 in an Access Query

  1. WHERE t2.MASE IN (...

    对于非常大的列表内集合操作,您可能会遇到性能障碍。在 Oracle 数据库服务器上,我与其他开发人员一起发现列表内查询运算符中离散元素的数量存在限制。该值以千计……根据服务器和数据库资源,可能会进一步受到限制。

    考虑使用 SQL JOIN 运算符。您定义TABLE 对象的位置也可以填充SQL 定义的查询,其别名称为INLINE VIEWS。由于您使用的是 ACCESS,如果内联视图不能直接工作,只需定义另一个 ACCESS QUERY 对象并在最终查询中引用它,就好像它是一个表一样...

    可能重写原始查询的结尾部分:

    SELECT 
       t2.Loc, 
       t2.ABCByPick, 
       t2.Planner, 
       ...
    
    FROM TempTableAnalysis AS t2,
       (SELECT TOP 10 t1.MASE, t1.ABCByPick
          FROM TempTableAnalysis AS t1) AS ttop
    
    WHERE t2.MASE = ttop.MASE
      AND t2.ABCByPick = ttop.ABCByPick
    
    ORDER BY
       t2.ABCByPick, 
       t2.MASE DESC;
    

您肯定需要仔细阅读这些建议并验证输出数据的准确性。这代表了捕获一些“容易实现的目标”(简单项目)的方法,您可以采用这些方法来加快查询和报告操作。

结论和结束语

作为其他读者的背景,数据库对象TempTableAnalysis 不是静态表。这是另一个 SO 帖子中提出的子查询的结果,该帖子请求Access TOP N Query 的帮助。查询来自多个表,大小接近 10,000 条记录(每个?)。

提示: Access 中的查询结果还具有潜在的类似表的行为。您可以将输出推送到表中以进行连接(如上所述)或仅连接到查询对象本身(但要小心,尤其是当您“链接”多个查询操作时...)

这个解决方案的策略是:

  1. 尽量减少通过这个超大表的一个或多个实例的次数。

  2. 预处理和索引优化任何在分析期间可能是“静态”的数据。

  3. 审核和审查用于获得最终结果的 SQL 代码。

一定要查看 Access MACROS。再加上识别数据集中的静态数据,您可以卸载复杂后台分析查询的处理,以改善用户在查看和查询最终结果时的体验。祝你好运!

【讨论】:

  • 感谢 Richard 的帮助和建设性意见。不幸的是,子查询 (SELECT TOP 10...) 没有按组选择前 10 个(在本例中按 ABCByPick),而只选择 TempTableAnalysis 表中的前 10 个。我想获得 ABCByPick = A 的最佳 10 MASE、ABCByPick = B 的最佳 10 MASE、ABCByPick = C 的最佳 10 MASE 等。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-22
相关资源
最近更新 更多