我在Axapta数据库上写了一个查询并重写了一百次,但问题仍然存在。它表现非常糟糕。 15分钟后,几乎没有结果,几乎让服务器停机。
欢迎任何有关如何改进此声明的想法。
SELECT
J.INVOICEID,
T.AMOUNTCUR,
T.RECID,
T.ACCOUNTNUM,
CASE WHEN O.DATAAREAID IS NULL THEN 0 ELSE 1 END hasOpenTrans,
CASE WHEN P.DATAAREAID IS NULL THEN 0 ELSE 1 END hasPayment
FROM
CUSTINVOICEJOUR J
LEFT JOIN CUSTTRANS T ON
T.DATAAREAID = J.DATAAREAID AND
T.INVOICE = J.INVOICEID AND
T.ACCOUNTNUM = J.INVOICEACCOUNT AND
T.TRANSDATE = J.INVOICEDATE
LEFT JOIN (
SELECT
DATAAREAID,
REFRECID,
ACCOUNTNUM
FROM
CUSTTRANSOPEN
GROUP BY
DATAAREAID,
REFRECID,
ACCOUNTNUM
HAVING
COUNT(*) > 0) O ON
O.DATAAREAID = T.DATAAREAID AND
O.REFRECID = T.RECID AND
O.ACCOUNTNUM = T.ACCOUNTNUM
LEFT JOIN (
SELECT
S.DATAAREAID,
S.TRANSCOMPANY,
S.TRANSRECID,
S.ACCOUNTNUM
FROM CUSTSETTLEMENT S
INNER JOIN CUSTTRANS C ON
C.DATAAREAID = S.DATAAREAID AND
C.RECID = S.OFFSETRECID AND
C.TRANSTYPE IN (0, 8, 15) AND
S.CANBEREVERSED = 1
GROUP BY
S.DATAAREAID,
S.TRANSRECID,
S.TRANSCOMPANY,
S.ACCOUNTNUM
HAVING
SUM(S.SETTLEAMOUNTCUR) > 0) P ON
P.DATAAREAID = T.DATAAREAID AND
P.TRANSRECID = T.RECID AND
P.ACCOUNTNUM = T.ACCOUNTNUM AND
P.TRANSCOMPANY = T.DATAAREAID
WHERE
J.DATAAREAID = '011' AND
J.INVOICEDATE >= '2014-06-01'
因为它可能很重要:这里是涉及的表上的现有索引:
CUSTINVOICEJOUR
Index Name Columns Clustered Primary Key Unique
I_062INVOICEACCOUNTIDX DATAAREAID, INVOICEACCOUNT, INVOICEDATE False False False
I_062INVOICENUMIDX DATAAREAID, INVOICEID, INVOICEDATE, NUMBERSEQUENCEGROUP, RECID True False True
I_062ORDERACCOUNTIDX DATAAREAID, ORDERACCOUNT, INVOICEDATE False False False
I_062PARMIDX DATAAREAID, PARMID False False False
I_062RECID DATAAREAID, RECID False True True
I_062SALESIDDATEIDX DATAAREAID, SALESID, REFNUM, INVOICEDATE False False False
I_062VATNUMIDX DATAAREAID, VATNUM False False False
CUSTTRANS
Index Name Columns Clustered Primary Key Unique
I_078ACCOUNTDATEIDX DATAAREAID, ACCOUNTNUM, TRANSDATE True False False
I_078BILLOFEXCHANGEIDX DATAAREAID, BILLOFEXCHANGEID False False False
I_078INVACCOUNTDATEIDX DATAAREAID, INVOICE, ACCOUNTNUM, TRANSDATE False False False
I_078INVOICEACCOUNTIDX DATAAREAID, INVOICE, ACCOUNTNUM False False False
I_078PAYMIDDATEIDX DATAAREAID, PAYMID, TRANSDATE False False False
I_078RECID DATAAREAID, RECID False True True
I_078VOUCHERDATEIDX DATAAREAID, VOUCHER, TRANSDATE False False False
CUSTTRANSOPEN
Index Name Columns Clustered Primary Key Unique
I_865ACCOUNTDATEIDX DATAAREAID, ACCOUNTNUM, TRANSDATE True False False
I_865RECID DATAAREAID, RECID False True True
I_865REFRECIDX DATAAREAID, REFRECID False False False
CUSTSETTLEMENT
Index Name Columns Clustered Primary Key Unique
I_075OFFSETCOMPANYRECTRANSREC7 DATAAREAID, OFFSETCOMPANY, OFFSETRECID, TRANSRECID, SETTLEMENTGROUP False False False
I_075OFFSETVOUCHERIDX DATAAREAID, OFFSETTRANSVOUCHER False False False
I_075RECID DATAAREAID, RECID False True True
I_075SETTLEMENTGROUPIDX DATAAREAID, SETTLEMENTGROUP False False False
I_075TRANSINDEX DATAAREAID, TRANSRECID, TRANSDATE True False False
表格的大小也可能很重要,或者至少可以了解我正在处理的记录数量:
CUSTINVOICEJOUR
DATAAREAID Nbr
011 1513668
012 2
ash 355735
bar 268795
euk 692242
hlm 866154
lil 136163
prv 3180
CUSTTRANS
DATAAREAID Nbr
011 2383870
012 4
ash 428161
bar 367620
bol 45
euk 630029
hlm 1377005
lil 167405
prv 4148
CUSTTRANSOPEN
DATAAREAID Nbr
011 6119
012 4
ash 5845
bar 1876
bol 29
euk 8077
hlm 2426
lil 2173
prv 190
CUSTSETTLEMENT
DATAAREAID Nbr
011 2469546
ash 462982
bar 415329
bol 18
euk 684421
hlm 1419857
lil 178551
prv 4325
答案 0 :(得分:0)
在不了解执行计划或各列数据的selectivity的情况下,并考虑到您发布的查询和索引,尝试在表上创建覆盖索引可能是值得的。
快速浏览一下查询会引导我查看所涉及的表的以下索引(基本上使用WHERE
子句中涉及的每一列,或JOIN
:
CUSTINVOICEJOUR - DATAAREAID, INVOICEID, NVOICEACCOUNT, INVOICEDATE, RECID, ACCOUNTNUM
CUSTTRANS - DATAAREAID, INVOICE, ACCOUNTNUM, TRANSDATE, RECID
CUSTTRANSOPEN - DATAAREAID, REFRECID, ACCOUNTNUM
CUSTSETTLEMENT - DATAAREAID, RECID, TRANSTYPE, CANBEREVERSED, TRANSRECID, ACCOUNTNUM, TRANSCOMPANY
请记住,列的上述顺序基于我在查询中发现它们的顺序。为了找出理想的顺序,确定每列的选择性,并根据它从高选择性到低的顺序对它们进行排序。
在添加新索引之前尝试并记录选择性路径,然后添加索引并再次检查执行路径以查看是否正在使用新索引(它们应该是。如果不是,它可能表示列缺失)。然后转到下一个索引,同时关注你刚刚添加的索引,看看你刚刚添加的索引是否会影响刚刚执行的路径(如果你抓到所有索引,就不会发生这种情况)使用的列,但这种行为永远不能排除100%)。
要注意的另一件好事是服务器返回的统计信息。添加新索引时,目标应该是降低物理读取量(基于磁盘的搜索),并将它们转换为逻辑读取(从内存中更便宜)。
您的里程可能会有所不同,但上述情况会让您有个良好的开端。
答案 1 :(得分:0)
也许somthing配置错误或某些其他进程正在锁定表格? 我在一个本地数据库上执行了你的查询,它在大约1秒内执行。
查看SQL服务器上的运行进程并搜索锁。 您可以使用查询分析器,它是SSMS的一部分。
来自这个地方的执行计划: