Sql 优化聚合查询

Sql 优化聚合查询,sql,tsql,Sql,Tsql,我有一个观点突然变得太慢,我不知道如何优化它。这些表当前分别包含15000行(@dispatchPallet)和135000行(@pickLog) 我已经编写了一段最小化的代码来显示下面的重要部分 DECLARE @dispatchPallet TABLE ( [PICK_PALL_NUM] [bigint] NOT NULL, [PALLET_PLACEMENT] [nvarchar](4) NOT NULL, [SHIPMENT_ID] [nvarchar](255

我有一个观点突然变得太慢,我不知道如何优化它。这些表当前分别包含15000行(@dispatchPallet)和135000行(@pickLog)

我已经编写了一段最小化的代码来显示下面的重要部分

DECLARE @dispatchPallet TABLE 
(
    [PICK_PALL_NUM] [bigint] NOT NULL,
    [PALLET_PLACEMENT] [nvarchar](4) NOT NULL,
    [SHIPMENT_ID] [nvarchar](255) NULL
)

DECLARE @pickLog TABLE 
(
    [LINE_NUM] [int] NOT NULL,
    [QTY_PRE] [numeric](9, 2) NULL,
    [QTY_SUF] [numeric](9, 2) NULL,
    [PICK_PALL_NUM] [bigint] NULL,
    [ROWID] [uniqueidentifier] NOT NULL,
    [WEIGHT_GROSS] [numeric](9, 3) NULL,
    [VOLUME] [numeric](9, 3) NULL
)


INSERT INTO @dispatchPallet ([PICK_PALL_NUM], [PALLET_PLACEMENT], [SHIPMENT_ID])
VALUES 
(4797753, 'B', 'SHIPMENT-1'),
(4797752, 'B', 'SHIPMENT-2'),
(4797750, 'B', 'SHIPMENT-3'),
(4797749, 'B', 'SHIPMENT-4'),
(4797739, 'B', 'SHIPMENT-5'),
(4797732, 'B', 'SHIPMENT-6'),
(4797731, 'B', 'SHIPMENT-7'),
(4797730, 'B', 'SHIPMENT-7'),
(4797723, 'B', 'SHIPMENT-8'),
(4797713, 'B', 'SHIPMENT-9')

INSERT INTO @pickLog ([LINE_NUM], [QTY_PRE], [QTY_SUF], [PICK_PALL_NUM], [ROWID], [WEIGHT_GROSS])
VALUES 
(30, 54, 54, 4797753, NEWID(), 1070.280),
(10, 24, 24, 4797752, NEWID(), 471.360),
(30, 12, 12, 4797750, NEWID(), 237.960),
(320, 25, 25, 4797749, NEWID(), 102.750),
(110, 3, 3, 4797739, NEWID(), 40.650),
(40, 12, 12, 4797732, NEWID(), 238.080),
(50, 4, 4, 4797732, NEWID(), 78.560),
(20, 20, 20, 4797731, NEWID(), 110.000),
(20, 40, 40, 4797730, NEWID(), 220.000),
(1340, 3, 3, 4797723, NEWID(), 14.250),
(410, 2, 2, 4797723, NEWID(), 4.780),
(440, 2, 2, 4797723, NEWID(), 21.000),
(480, 1, 1, 4797723, NEWID(), 3.500),
(1290, 2, 2, 4797723, NEWID(), 39.280),
(470, 1, 1, 4797723, NEWID(), 8.500),
(280, 3, 3, 4797723, NEWID(), 16.500),
(10, 2, 2, 4797723, NEWID(), 10.700),
(500, 2, 2, 4797723, NEWID(), 6.600),
(290, 1, 1, 4797713, NEWID(), 0.540),
(40, 2, 2, 4797713, NEWID(), 33.800)

SELECT 
    [dispatchPallet].[SHIPMENT_ID], 
    SUM([pickLog].[QTY_SUF]) AS KOLLI,
    COUNT(DISTINCT [pickLog].[LINE_NUM]) AS LINES,
    SUM([pickLog].[WEIGHT_GROSS]) AS PICKED_WEIGHT, 
    COUNT(DISTINCT [pickLog].[PICK_PALL_NUM]) AS PALLETS,
    COUNT(DISTINCT CASE WHEN [dispatchPallet].[PALLET_PLACEMENT] = 'B' THEN [dispatchPallet].[PICK_PALL_NUM] ELSE NULL END) AS BOTTOM_PALLETS       
FROM 
    @dispatchPallet dispatchPallet 
    INNER JOIN @pickLog pickLog ON [dispatchPallet].[PICK_PALL_NUM] = [pickLog].[PICK_PALL_NUM]
GROUP BY 
    [dispatchPallet].[SHIPMENT_ID]

-- Expected output:
-- SHIPMENT_ID  KOLLI   LINES   PICKED_WEIGHT   PALLETS BOTTOM_PALLETS
-- SHIPMENT-1   54.00   1       1070.280        1       1
-- SHIPMENT-2   24.00   1       471.360         1       1
-- SHIPMENT-3   12.00   1       237.960         1       1
-- SHIPMENT-4   25.00   1       102.750         1       1
-- SHIPMENT-5   3.00    1       40.650          1       1
-- SHIPMENT-6   16.00   2       316.640         1       1
-- SHIPMENT-7   60.00   1       330.000         2       2
-- SHIPMENT-8   18.00   9       125.110         1       1
-- SHIPMENT-9   3.00    2       34.340          1       1 

首先,这些表上应该有主键和外键,这样这个查询就可以进行索引搜索/扫描(上面是狗仔队的评论),而不是完整的表搜索/扫描


除了bigint/int之外,uniqueidentifier的用途是什么

您的查询很简单,没有多少优化空间。您应该检查是否至少在
dispatchPallet
by
shipping\u ID
pickLog
by
PICK\u PALL\u NUM
上有索引。以下是查询的最佳选择:

CREATE NONCLUSTERED INDEX NCI_dispatchPallet_shipment_ID 
    ON dispatchPallet (SHIPMENT_ID, PICK_PALL_NUM)
    INCLUDE (PALLET_PLACEMENT)


CREATE NONCLUSTERED INDEX NCI_pickLog_pick_pall_num 
    ON pickLog (PICK_PALL_NUM)
    INCLUDE (QTY_SUF, LINE_NUM, WEIGHT_GROSS)
您还应该验证是否需要将
计数
设置为
独立的
(独立是一项昂贵的操作)


最后但并非最不重要的一点是,您应该真正检查如何访问视图;如果您正在筛选它、加入它,等等。这些其他条件可能会生成不同的查询计划,并且如果管理不正确(即使使用了正确的索引!),可能会导致性能下降。

您至少应该在as上创建主约束

ALTER TABLE @dispatchPallet TABLE   ADD PRIMARY KEY (PICK_PALL_NUM);
外键约束为

ALTER TABLE @pickLog TABLE  ADD foreign key (PICK_PALL_NUM) references @dispatchPallet(PICK_PALL_NUM)
还可以在上创建唯一索引

CREATE UNIQUE NONCLUSTERED INDEX idx_PALLET_PLACEMENT_notnull
ON @dispatchPallet(PALLET_PLACEMENT)
WHERE PALLET_PLACEMENT IS NOT NULL;

你能给我看一下这个计划吗?而且,“突然变得太慢”让我想到了一个统计问题。所有的表统计信息都是最新的吗?为什么视图需要事务?真正的表有索引吗?发布查询计划。你真的需要大整数吗?@狗仔队视图中没有事务,这只是出于测试目的的习惯。问题的主要焦点是SELECT-如果有更好的方法来执行DISTINCT/SUM/CASE/COUNT。@ThomasG我如何检查?对我来说,“突然”是当表格有一天稍微变大时(我们只保存了4天的信息)。(这主要是DBA的事情)在这个特定的表查询中,实际上并不需要uniqueidentifier。但这是为了表上的其他查询。此外,还需要bigint,不要过多地查看示例中的特定数据。uniqueidentifier是表的主键。这不是我自己创造的。。在提货数量和发货ID上有一个索引,所以这不应该是一个问题。我已经查看了索引,它们使它稍微快一点。“如何访问视图”到底是什么意思?视图本身只是一个语法快捷方式,它不能保证SQL引擎使用正确的索引。“访问视图”是指您实际查询视图时使用的SQL
SELECT*fromYourView
SELECT*fromYourView内部连接其他表在SomeColumn=OtherColumn=9142
中完全不同。整体性能将高度依赖于过滤器和与其他表的联接。视图的选择非常像这样:“按PICK\u PALL\u NUM DESC从视图顺序选择*”。那么,您只需调整此SQL就可以做得不多了。检查查询执行计划,确保正在使用我们提到的索引,并且它们的碎片非常小(如果很大,则重建)。除此之外,由于网络问题、服务器过载或其他操作在查询时阻塞了表,可能会导致性能下降。