3

我正在使用 mssql 服务器 2008r2。我有一个巨大的表格,其中包含 19 个商店的营业额数据,逐日逐项。它有大约 1 亿行。但是使用分区视图很容易运行查询。

表的结构如下所示:

  1. 店铺名称
  2. 商品编号
  3. 日期
  4. 周转
  5. 销售数量

输出报告如下所示:Item id, date, store_1.turnover, store_1.quantity, store_2.turnover, store_2.quantity....

要创建这种报告,我使用以下查询:

WITH cte_sell AS(
    SELECT * 
    FROM view_turnover 
    WHERE date BETWEEN '130413' and '130418' )

SELECT a.item_id,a.date,
    store_1.turnover,store_1.quantity,
    store_2.turnover,store_2.quantity,
    store_3.turnover,store_3.quantity

FROM (SELECT DISTINCT item_id,date FROM cte_sell) as a
LEFT JOIN (SELECT * FROM cte_sell WHERE store='Store 1') as Store_1 ON a.item_id=store_1.item_id and a.date=store_1.date    
LEFT JOIN (SELECT * FROM cte_sell WHERE store='Store 2') as Store_2 ON a.item_id=store_2.item_id and a.date=store_2.date    
LEFT JOIN (SELECT * FROM cte_sell WHERE store='Store 3') as Store_3 ON a.item_id=store_3.item_id and a.date=store_3.date

我希望你能理解查询。

对于 14-15 存储(14 15 LEFT JOIN),查询运行不到 10 秒,这很好。但问题是当我选择所有 19 个商店(19 个 LEFT JOIN)时,查询会显着减慢。完成可能需要 2 或 3 分钟。

执行计划的创建也更长:

  • 12家店只需2秒
  • 19店22秒

你怎么看,表加入有什么限制吗?我认为有一些服务器参数可以控制大量查询。有谁知道如何优化查询或服务器?

最糟糕的是,服务器有时会冻结:我在 9 点和 12 点运行查询时创建了一个跟踪文件。在 9 点,运行查询需要 2 分钟。在 12 时,我不得不在 10 分钟后重新启动计算机,因为我无法从配置管理器重新启动 SQL 服务。

我不能附上截图。

在活动监视器中,进程处于挂起状态。等待类型是:CXPACKET 等待资源是:exchang.... 抱歉,我对锁了解不多。

我尝试从管理工作室连接并收到此消息:与服务器成功建立连接,但在登录过程中发生错误。(提供者:TCP 提供者,错误:0(翻译自匈牙利语):现有连接被远程机器强制关闭。

4

2 回答 2

1

您是否考虑过删除子查询并仅使用连接条件?

WITH cte_sell AS(
    SELECT * 
    FROM view_turnover 
    WHERE date BETWEEN '130413' and '130418' )

SELECT a.item_id,a.date,
    store_1.turnover,store_1.quantity,
    store_2.turnover,store_2.quantity,
    store_3.turnover,store_3.quantity

FROM (SELECT DISTINCT item_id,date FROM cte_sell) as a
LEFT JOIN cte_sell as Store_1 ON a.item_id=store_1.item_id and a.date=store_1.date and Store='Store 1'
LEFT JOIN cte_sell as Store_2 ON a.item_id=store_2.item_id and a.date=store_2.date and store='Store 2'
LEFT JOIN cte_sell as Store_3 ON a.item_id=store_3.item_id and a.date=store_3.date and store='Store 3'
于 2013-05-01T16:36:43.760 回答
0

我认为问题在于 SQL Server 在查询中多次出现时似乎没有优化 CTE 表达式。换句话说,如果您查看执行计划,视图将被执行 3 次——针对每个提及商店。

您可以将每个商店放在不同的行上吗?如果是这样,试试这个:

WITH cte_sell AS (
    SELECT * 
    FROM view_turnover 
    WHERE date BETWEEN '130413' and '130418'
   )
SELECT a.item_id, a.date, store, turnover, quantity
FROM (SELECT DISTINCT item_id,date FROM cte_sell) as a left join
     cte_sell cs
     on a.item_id=cs.item_id and a.date=cs.date and cs.store in ('Store 1', 'Store 2', 'Store 3')

如果你需要一排有多个商店,那么条件聚合还是pivot会解决问题的。

如果您想在一行中查看所有值,请在上述查询中使用条件聚合:

WITH cte_sell AS (
    SELECT * 
    FROM view_turnover 
    WHERE date BETWEEN '130413' and '130418'
   )
SELECT a.item_id, a.date,
       max(case when store = 'Store 1' then turnover end),
       max(case when store = 'Store 1' then quantity end),
       max(case when store = 'Store 2' then turnover end),
       max(case when store = 'Store 2' then quantity end),
       max(case when store = 'Store 3' then turnover end),
       max(case when store = 'Store 3' then quantity end)
FROM (SELECT DISTINCT item_id,date FROM cte_sell) as a left join
     cte_sell cs
     on a.item_id=cs.item_id and a.date=cs.date and cs.store in ('Store 1', 'Store 2', 'Store 3')
group by a.item_id, a.date
于 2013-05-01T15:38:39.237 回答