对于具有350,000条记录的最大表PremiseProviderBillings的数据库,以下SQL需要5秒。但是在具有150万条记录的相同数据库上,它需要一分钟
SELECT
n.CustomerInvoiceNumberId as InvoiceNo,C.CustomerBillId,c.customerid, S.Volumetric, S.Fixed, S.VAT, S.Discount, C.Debit,c.EffectiveDate,c.TransactionDateTime,s.Consumption,r.CustomerCreditNoteId--,s.Volumetric + s.Fixed + s.Vat - s.discount - c.debit as variance
FROM
CustomerPayments C
INNER JOIN
(SELECT
CustomerBillId, SUM(a.VolumetricCharge) as Volumetric,SUM(a.FixedCharge) as Fixed,
SUM(a.VAT) as VAT,SUM(a.Discount) as Discount,sum(a.EstimatedConsumption) as Consumption
FROM
PremiseProviderBillings a, PremiseProviderBills b
WHERE a.PremiseProviderBillId = b.PremiseProviderBillId
GROUP BY
CustomerBillId) S
ON
C.CustomerBillId = S.CustomerBillId
and debit <> 0 -- hide credit note lines, we mark these results with customerCreditNoteId to show they have been credited
INNER JOIN dbo.CustomerInvoiceNumbers n on c.CustomerBillId = n.CustomerBillId
left OUTER JOIN
dbo.CustomerCreditNotes AS r ON c.CustomerPaymentId = r.CustomerPaymentId
where isnull(c.transactionDateTimeEnd,'')=''
如果我然后运行内部SQL部分,它将较小数据库上的值相加,则需要2秒。在较大的数据库上需要34秒,内部SQL低于......
SELECT
CustomerBillId, SUM(a.VolumetricCharge) as Volumetric,SUM(a.FixedCharge) as Fixed,
SUM(a.VAT) as VAT,SUM(a.Discount) as Discount,sum(a.EstimatedConsumption) as Consumption
FROM
PremiseProviderBillings a, PremiseProviderBills b
WHERE a.PremiseProviderBillId = b.PremiseProviderBillId
GROUP BY
CustomerBillId
很明显,这个SQL根本无法扩展。鉴于数据库将增长应该采用哪种技术来改善这一点?
我检查了所有连接,以确保没有丢失的索引,以确保所有连接都是基于密钥的,确定
我原本以为这种方法没问题,但是我应该改变SQL的结构,这是不可扩展且效率低的吗?
此致
答案 0 :(得分:0)
尝试对内部查询使用公用表表达式,这可能会加快一些速度。
WITH CTE AS
(
SELECT
CustomerBillId, SUM(a.VolumetricCharge) as Volumetric,SUM(a.FixedCharge) as Fixed,
SUM(a.VAT) as VAT,SUM(a.Discount) as Discount,sum(a.EstimatedConsumption) as Consumption
FROM
PremiseProviderBillings a, PremiseProviderBills b
WHERE a.PremiseProviderBillId = b.PremiseProviderBillId
GROUP BY
CustomerBillId
)
SELECT
n.CustomerInvoiceNumberId as InvoiceNo,C.CustomerBillId,c.customerid, S.Volumetric, S.Fixed, S.VAT, S.Discount, C.Debit,c.EffectiveDate,c.TransactionDateTime,s.Consumption,r.CustomerCreditNoteId--,s.Volumetric + s.Fixed + s.Vat - s.discount - c.debit as variance
FROM
CustomerPayments C
INNER JOIN
CTE S
ON
C.CustomerBillId = S.CustomerBillId
and debit <> 0 -- hide credit note lines, we mark these results with customerCreditNoteId to show they have been credited
INNER JOIN dbo.CustomerInvoiceNumbers n on c.CustomerBillId = n.CustomerBillId
left OUTER JOIN
dbo.CustomerCreditNotes AS r ON c.CustomerPaymentId = r.CustomerPaymentId
where isnull(c.transactionDateTimeEnd,'')=''
答案 1 :(得分:0)
如果您经常使用该查询,并且根据您写入表的频率,可能值得为此创建indexed view。然而值得注意的是,这是猜测,并且索引视图确实带来了折衷,您的读取速度会更快但写入速度会更慢。
CREATE VIEW dbo.CustomerBillingView
WITH SCHEMABINDING
AS
SELECT b.CustomerBillId,
SUM(a.VolumetricCharge) AS Volumetric,
SUM(a.FixedCharge) AS Fixed,
SUM(a.VAT) AS VAT,
SUM(a.Discount) AS Discount,
SUM(a.EstimatedConsumption) AS Consumption,
COUNT_BIG(*) AS Records -- REQUIRED TO CREATE INDEX
FROM dbo.PremiseProviderBillings a
INNER JOIN dbo.PremiseProviderBills b
ON a.PremiseProviderBillId = b.PremiseProviderBillId
GROUP BY b.CustomerBillId;
GO
CREATE UNIQUE CLUSTERED INDEX UQ_CustomerBillingView__CustomerBillId
ON dbo.CustomerBillingView (CustomerBillId);
GO
然后,您只需要使用提示NOEXPAND
的视图来确保使用索引。
SELECT n.CustomerInvoiceNumberId as InvoiceNo,
c.CustomerBillId,
c.customerid,
s.Volumetric,
s.Fixed,
s.VAT,
s.Discount,
c.Debit,
c.EffectiveDate,
c.TransactionDateTime,
s.Consumption,
r.CustomerCreditNoteId
--,s.Volumetric + s.Fixed + s.Vat - s.discount - c.debit as variance
FROM CustomerPayments AS c
INNER JOIN dbo.CustomerBillingView AS s WITH (NOEXPAND)
ON c.CustomerBillId = s.CustomerBillId
AND c.Debit <> 0
-- hide credit note lines, we mark these results with customerCreditNoteId to show they have been credited
INNER JOIN dbo.CustomerInvoiceNumbers n
ON c.CustomerBillId = n.CustomerBillId
LEFT OUTER JOIN dbo.CustomerCreditNotes AS r
ON c.CustomerPaymentId = r.CustomerPaymentId
WHERE ISNULL(c.transactionDateTimeEnd,'') = '';
与每个查询调优问题一样,您是唯一拥有正确回答所需信息的人。 根据我的经验(主要在计费系统中),像这样的索引视图通常可以使用结算数据,因为大多数发票运行都是周期性的, 所以写入是批量而不是连续的,并且读取也往往超过写入,因为数据是静态的,一旦创建了发票然后它 很少更新。