如何解决SQL 查询在 SQL Server CE 中很慢,但在 SQL Server 中很快
我正在开发一个需要同时支持 sql Server 和 sql Server CE (4.0) 的产品。
客户 |
---|
id |
名称 |
订单 |
---|
id |
客户 ID |
创建 |
我需要创建一个包含所有客户以及订单总数的列表。
由于 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 上的查询变得非常慢,即使使用“ FETCH NEXT 10 ROWS ONLY”仅获取 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],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
SELECT customerId,Count(o.id) as total
FROM orders AS o
WHERE customerID IN ([ids from query above])
GROUP BY customerId
这在大约 200 毫秒内执行......这太奇怪了。
解决方法
首先,非常感谢@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 查询似乎是最好的选择。
感谢所有花时间帮助我的人!
,拆分为两个查询,一个用于获取客户 ID,另一个用于获取相关订单,并确保两个查询都有良好的索引。
如果您要获取所有客户,请考虑获取所有订单的计数,以避免出现大的 IN 情况。
很高兴帮助您调查您是否私下共享数据库和查询。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。