SQL 查询在 SQL Server CE 中很慢,但在 SQL Server 中很快

Posted

技术标签:

【中文标题】SQL 查询在 SQL Server CE 中很慢,但在 SQL Server 中很快【英文标题】:SQL-query slow in SQL Server CE but fast in SQL Server 【发布时间】:2021-01-10 01:52:48 【问题描述】:

我正在开发一个需要同时支持 SQL Server 和 SQL Server CE (4.0) 的产品。

我有两个表,一个是实体,另一个是关系表,如下所示:

Customer
id
name
Order
id
customerId
created

我需要创建一个包含所有客户的列表以及订单总数。

由于 SQL Server CE 中存在限制,例如不能在选择语句中使用子查询,我想我可以这样查询:

SELECT [id]
      ,[name]
      ,ordersCount.total as totalOrders
  FROM [customer] as c
  LEFT JOIN(
        SELECT customerId, Count(o.id) as total FROM orders AS o GROUP BY customerId
  ) as orderCount ON c.id = orderCount.customerId
ORDER BY id
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY

此查询在 SQL Server CE 和 SQL Server 中都有效,如果行数很少,它会非常快,但是当我们有很多或行时,查询在 SQL Server CE 上变得非常慢,即使使用 "仅获取下一个 10 行”以仅获取 10 行。我猜想即使我只获取 10 行,也会对所有行执行 LEFT-join。

执行查询的“部分”时间不到 100 毫秒,

SELECT customerId, Count(o.id) as total FROM orders AS o WHERE GROUP BY customerId

在 SQL Server CE 上需要 50 毫秒

SELECT [id]
      ,[name]
      ,ordersCount.total as totalOrders
  FROM [customer] as c

在 SQL Server CE 上需要 80 毫秒

但是当我使用 LEFT JOIN 执行整个查询时,查询需要 2 分钟以上(大约 14 000 名客户有 17-18 000 个订单。

执行计划表明“嵌套循环”占用了 100% 的时间用于 SQL Server CE 中的处理。但我似乎无法弄清楚为什么?

我有以下索引:

customer.id(PK。包括:customer.id) order.customerId(包括 order.customerId)

我想知道是否有某种方法可以使 SQL Server CE 上的查询更快?另外,我可以用另一种方式查询并获得相同的结果但更高效吗?

编辑: 我尝试将查询分为两个查询,首先获取即将显示的 50 个客户,然后查询计数。

SELECT [id]
      ,[name]
  FROM [customer] as c
ORDER BY id
OFFSET 0 ROWS
FETCH NEXT 50 ROWS ONLY

然后从这 50 个中取出 id 并查询计数:

SELECT customerId, Count(o.id) as total 
FROM orders AS o 
WHERE customerID IN ([ids from query above])
GROUP BY customerId

这在大约 200 毫秒内执行......这太奇怪了。

【问题讨论】:

请在您的帖子中编辑您的索引是什么,并通过PasteThePlan.com分享查询计划 @Charlieface 我已经包含了索引(custom.id 和 order.customerId),试图将计划粘贴到您提供的链接中,但它说计划是无效的 XML,但我可以在 SSMS 中打开它。 完整的索引定义,带有INCLUDEs。您是否在复制所有 XML,您可能错过了一个标签?还有 SQL Server 上的查询计划,以便我们进行比较。猜测一下,如果没有看到完整的计划,合并连接会更好,但由于某种原因没有选择 您的文字有误或已删除。 WHERE GROUP BY 是什么意思 我只是尝试将“LEFT JOIN”切换为“INNER JOIN”,它在不到 100 毫秒内执行。但有时客户可以在没有订单的情况下存在。感觉好奇怪,左连接和内连接能有这么大的区别?我已经更新到完整的索引描述。 【参考方案1】:

首先,非常感谢@ErikEJ,他非常好心地私下帮助了我。真是个好人,乐于助人!

ErikEJ 指出了我不知道的一件事,即 SQLCE 每个表和问题只使用一个索引,这可能对将来很有帮助。

在摆弄并阅读了这篇文章之后,我想出了尝试“CROSS APPLY”查询的想法。

类似这样的:

SELECT [id]
      ,[name]
      ,ot.total as totalOrders
  FROM [customer] as c
  CROSS APPLY (SELECT Count(o.id) as total FROM orders AS o WHERE o.customerId = c.id) as ot
ORDER BY id
OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY

此查询在 SQL Server 上执行大约 1 毫秒,在 SQLCE 上大约 300 毫秒。在性能方面,在这种情况下,获取前 50 行并基于它们使用组查询获取 COUNT() 仍然快 225% 左右。但是,如果需要对计数(哪个 id 需要)进行排序,CROSS APPLY-query 似乎是最好的选择。

感谢所有花时间帮助我的人!

【讨论】:

【参考方案2】:

分成两个查询,一个用于获取客户 ID,另一个用于获取相关订单并确保两个查询都有良好的索引。

如果您要获取所有客户,请考虑获取所有订单的计数,以避免出现较大的 IN 条件。

很高兴帮助您调查您是否私下共享数据库和查询。

【讨论】:

“获取 50 个 id”解决方案非常适合这个用例,因为它不是基于计数的排序,但如果是这样的话,我仍然需要在查询中进行排序.我可以以某种方式私下分享 SQLCE 文件和查询,不想在这里全部发布 - 我应该离开 twitter 还是你更喜欢什么? 发邮件给我,地址在 Github 在您的 github 页面上找不到您的电子邮件,在您的博客上也没有,而且您在 Twitter 上禁用了 PM...=/ 哦,设法在你的旧博客上找到一些东西 =D 希望这个是正确的:ej*****@hotmail.com,我已经给你发了一封电子邮件。

以上是关于SQL 查询在 SQL Server CE 中很慢,但在 SQL Server 中很快的主要内容,如果未能解决你的问题,请参考以下文章

简单查询在 laravel 中很慢(带有分页)但在 phpmyadmin 中非常快

在 WP7.1 SQL Server CE 数据库上执行 SQL 查询

在 SQL Server CE 中解析查询时出错

打开多个查询时访问 SQL-Server 很慢

SQL 按问题分组 SQL Server 2005 CE

sql server执行几十万条sql很慢,怎么办?