我正在使用mssql server 2008r2。 我有一个巨大的表格,每天包含19个商店营业额数据。它有大约1亿行。但是通过分区视图,可以轻松运行查询。
表的结构如下所示:
输出报告如下所示: 商品ID,日期,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分钟。
执行计划的创建时间也要长得多:
您如何看待,表格加入是否有任何限制? 我认为有一些服务器参数可以控制巨大的查询。 有谁知道如何优化查询或服务器?
最糟糕的是,服务器有时会冻结:我在9点钟和12点运行查询时创建了一个跟踪文件。 9点运行查询需要2分钟。 在12点,我在10分钟后重新启动了comupetr,因为我无法从配置管理器重新启动SQL服务。
我无法附上screnshots。
在活动监视器中,进程处于挂起状态。 等待类型是:CXPACKET 等待资源是:交换.... 对不起,但我对锁不太了解。
我尝试从管理工作室连接并收到此消息:已成功与服务器建立连接,但在登录过程中出现错误。 (提供者:TCP提供者,错误:0(翻译自匈牙利语):远程机器强制关闭现有连接。
答案 0 :(得分: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'
答案 1 :(得分:0)
我认为问题在于SQL Server在查询中多次出现时似乎没有优化它们。换句话说,如果您查看执行计划,则视图将被执行三次 - 对于每个提及商店。
您可以将每个商店放在不同的行上吗?如果是这样,试试这个:
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