【问题标题】:Slow SQL Code on local server in MS AccessMS Access 中本地服务器上的慢速 SQL 代码
【发布时间】:2008-11-11 15:18:43
【问题描述】:

我有一个特定的 SQL 语句,它需要大约 30 秒才能执行,我想知道是否有人可以看到它的问题,或者我需要额外索引的地方。

代码位于 Access 中的子表单上,它显示的结果取决于主表单中五个字段的内容。正在查询的表中有近 5000 条记录。 Access 项目是从实际 SQL 服务器上的终端服务器会话存储和运行的,所以我认为这不是网络问题,还有另一种形式非常相似,使用相同类型的查询...

谢谢

PG

SELECT TabDrawer.DrawerName, TabDrawer.DrawerSortCode, TabDrawer.DrawerAccountNo, TabDrawer.DrawerPostCode, QryAllTransactons.TPCChequeNumber, tabdrawer.drawerref
FROM TabDrawer LEFT JOIN QryAllTransactons ON  TabDrawer.DrawerRef=QryAllTransactons.tpcdrawer
WHERE (Forms!FrmSearchCompany!SearchName Is Null 
      Or [drawername] Like Forms!FrmSearchCompany!SearchName & "*") 
      And (Forms!FrmSearchCompany.SearchPostcode Is Null 
      Or [Drawerpostcode] Like Forms!FrmSearchCompany!Searchpostcode & "*") 
      And (Forms!FrmSearchCompany!SearchSortCode Is Null 
      Or [drawersortcode] Like Forms!FrmSearchCompany!Searchsortcode & "*") 
      And (Forms!FrmSearchCompany!Searchaccount Is Null 
      Or [draweraccountno] Like Forms!FrmSearchCompany!Searchaccount & "*") 
      And (Forms!FrmSearchCompany!Searchcheque Is Null 
      Or [tpcchequenumber] Like Forms!FrmSearchCompany!Searchcheque & "*");
    ");

编辑

Hold up 似乎在形成 QryAllTransactons 查询的联合查询中。

SELECT 
  "TPC" AS Type, 
  TabTPC.TPCRef, 
  TabTPC.TPCBranch, 
  TabTPC.TPCDate, 
  TabTPC.TPCChequeNumber, 
  TabTPC.TPCChequeValue, 
  TabTPC.TPCFee, 
  TabTPC.TPCAction,
  TabTPC.TPCMember, 
  tabtpc.tpcdrawer,
  TabTPC.TPCUser,
  TabTPC.TPCDiscount,
  tabcustomers.*
FROM 
  TabTPC 
  INNER JOIN TabCustomers ON TabTPC.TPCMember = TabCustomers.CustomerID

UNION ALL 

SELECT 
 "CTP" AS Type, 
  TabCTP.CTPRef, 
  TabCTP.CTPBranch, 
  TabCTP.CTPDate, 
  TabCTP.CTPChequeNumb, 
  TabCTP.CTPAmount, 
  TabCTP.CTPFee, 
  TabCTP.CTPAction,
  TabCTP.CTPMember,
  0 as CTPXXX,
  TabCTP.CTPUser,
  TabCTP.CTPDiscount, 
  TABCUSTOMERS.*
FROM 
  TabCTP  
  INNER JOIN TabCustomers ON Tabctp.ctpMember = TabCustomers.CustomerID;

我已经用简单的联合查询做了很多工作,但以前从未有过这种情况......

【问题讨论】:

  • 你说“访问项目”。这是ADP吗?如果是这样,那肯定会改变您需要的答案类型。
  • 我已经阅读了整个线程,但我仍然不知道它是 ADP->SQL Server 还是 MDB->ODBC->SQL Server。
  • 请马上回答大卫的问题

标签: sql ms-access


【解决方案1】:

两件事。由于这是一个带有 SQL Server 后端的 Access 数据库,因此将其转换为存储过程可能会显着提高速度。

其次,您真的需要返回所有这些字段,尤其是 tabCustomers 表中的字段吗?永远不要返回比您实际打算使用的更多的字段,这样您会提高性能。

【讨论】:

  • 这一针见血 - 有一个报告需要所有字段,但对于这种特殊情况,甚至不需要左连接 - 我创建了一个手表它创建了联合而不是存储过程,并且将速度提高了至少 50 倍。感谢大家的帮助:)
  • 如何将表单控件定义为第一个 SQL 语句中的参数?我不使用 ADP,但使用 MDB 或 ODBC->SQL Server 可以加快速度。在后一种情况下,它可以完全改变 Jet 传递给 SQL Server 的内容,我认为 ADP 会同样聪明(如果不是更聪明的话)。
【解决方案2】:

首先,尝试压缩和修复 .mdb 文件。

然后,简化您的 WHERE 子句:

WHERE
  [drawername] Like Nz(Forms!FrmSearchCompany!SearchName, "") & "*"
  And 
  [Drawerpostcode] Like Nz(Forms!FrmSearchCompany!Searchpostcode, "") & "*"
  And 
  [drawersortcode] Like Nz(Forms!FrmSearchCompany!Searchsortcode, "") & "*"
  And 
  [draweraccountno] Like Nz(Forms!FrmSearchCompany!Searchaccount, "") & "*"
  And 
  [tpcchequenumber] Like Nz(Forms!FrmSearchCompany!Searchcheque, "") & "*"

它仍然运行缓慢吗?

编辑

事实证明,问题并不明确,因为它是一个大型的 Access 数据库,带有一个 SQL Server 后端和一个 Access Project 前端。

这为整个问题提供了不同的视角。

您能否更详细地解释一下如何整个查询将被使用?

如果您使用它来填充某些表单或报告的 RecordSource,我认为您将能够像这样重构整个事情:

  • 在返回正确数据的 SQL 服务器上创建视图
  • 使用 SQL 服务器语法查询该视图,而不是使用 Access 语法
  • 让服务器整理一下

【讨论】:

  • 他正在使用一个访问项目文件,该文件本质上只是存储在 SQL Server 中的数据的前端(GUI 和一些 VBA),因此没有 MDB,也不需要修复。
  • 另一点要提的是,根据您的建议,查询应该更慢,因为代价高昂的部分是 like 运算符,现在您正在这样做,即使值为 null。
  • 真的吗?我在几个小时前就知道了。 cmets 继续讨论他的回答。在有机会找到问题之前,我没有看到更新答案的理由。
【解决方案3】:

QryAllTransactons 中有多少行?

如果您的结果返回 0 行,则 Access 可能会立即看到并停止,但如果它甚至返回单行,则它需要拉入 QryAllTransactons 的整个结果集,以便它可以在内部进行连接。这将是我对正在发生的事情的第一个猜测。

最好的办法通常是在 SQL Server 上进行连接。尝试创建一个执行 LEFT OUTER JOIN 的视图并对其进行查询。

即使 Access 在 SQL Server 本身上运行并最大限度地减少网络流量,您的目标也是仅向 Access 发送绝对需要的内容。否则大表还是会占用内存等。

【讨论】:

  • 我刚刚检查过,该查询有 166 行。
【解决方案4】:

您是否尝试过运行联合中的每个子查询?通常优化器不会花太多时间来检查联合元素之间的效率 - 每个元素都有自己的优点。

鉴于这一事实,您还可以将“IF”逻辑放入程序代码中,并以某种可能的发现顺序运行每个测试,而不会因更多调用而产生大量额外开销。

【讨论】:

    【解决方案5】:

    摆脱那些喜欢运营商的人。

    在您的情况下,您不需要它们。只需检查该字段是否以给定值开头,您可以通过以下方式实现:

    Left([field], Len(value)) = value
    

    应用于您的查询的这个方法看起来像这样(为了更好的可读性做了一些重新格式化):

    SELECT
      TabDrawer.DrawerName, 
      TabDrawer.DrawerSortCode, 
      TabDrawer.DrawerAccountNo, 
      TabDrawer.DrawerPostCode, 
      QryAllTransactons.TPCChequeNumber, 
      TabDrawer.DrawerRef
    FROM
      TabDrawer 
      LEFT JOIN QryAllTransactons 
        ON TabDrawer.DrawerRef = QryAllTransactons.TpcDrawer
    WHERE 
      (Forms!FrmSearchCompany!SearchName Is Null 
      Or Left([drawername], Len(Forms!FrmSearchCompany!SearchName)) = Forms!FrmSearchCompany!SearchName)
    And
      (Forms!FrmSearchCompany.SearchPostcode Is Null 
      Or Left([Drawerpostcode], Len(Forms!FrmSearchCompany!Searchpostcode)) = Forms!FrmSearchCompany!Searchpostcode) 
    And 
      (Forms!FrmSearchCompany!SearchSortCode Is Null 
      Or Left([drawersortcode], Len(Forms!FrmSearchCompany!Searchsortcode)) = Forms!FrmSearchCompany!Searchsortcode) 
    And 
      (Forms!FrmSearchCompany!Searchaccount Is Null 
      Or Left([draweraccountno], Len(Forms!FrmSearchCompany!Searchaccount)) = Forms!FrmSearchCompany!Searchaccount) 
    And 
      (Forms!FrmSearchCompany!Searchcheque Is Null 
      Or Left([tpcchequenumber], Len(Forms!FrmSearchCompany!Searchcheque)) = Forms!FrmSearchCompany!Searchcheque)
    

    请注意,您在比较区分大小写。我不完全确定 MS-Access 中的 like 运算符是否不区分大小写。如果需要,将两个字符串都转换为大写或小写。

    【讨论】:

      【解决方案6】:

      当您升迁时,您是否确保表已正确编入索引?如果使用得当,索引将大大加快查询速度(注意它们也可能减慢插入/更新/删除速度,因此请谨慎选择要索引的内容)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-13
        • 1970-01-01
        • 1970-01-01
        • 2018-07-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多