में धीरे-धीरे यह इतना सरल है: एक प्रश्न कि Oracle 11g से कनेक्ट कर SQL डेवलपर में बस कुछ ही सेकंड में चलाता है SSRS 2008 R2 में 15-25 मिनट लगते हैं। मैंने एसएसआरएस के अन्य संस्करणों की कोशिश नहीं की है। अब तक मैं वीएस 2008 से सभी रिपोर्ट निष्पादन कर रहा हूं।क्वेरी Oracle SQL डेवलपर में जल्दी से चलाता है, लेकिन SSRS 2008 R2
मैं ओएलई डीबी प्रदाता "OraOLEDB.Oracle.1" का उपयोग कर रहा हूं, जो अतीत में मुझे ओरेकल प्रदाता का उपयोग करने से बेहतर परिणाम देने लग रहा था।
यहाँ मैं अब तक यह निर्धारित करने के लिए सक्षम किया गया है या नहीं:
• देरी डेटासेट निष्पादन चरण के दौरान और परिणाम सेट या समय प्रतिपादन के साथ कोई संबंध नहीं है। (एक मेज मैं करने के लिए इसे डाला से सीधे ही rowset का चयन करके प्रमाणन।)
• SSRS ही काट दिया नहीं है। यह वास्तव में ओरेकल के लिए इंतजार कर रहा है, जहां देरी है (ओरेकल पक्ष से डीबी सत्र को समाप्त करके साबित हुआ, जिसके परिणामस्वरूप सत्र के बारे में एसएसआरएस में त्वरित त्रुटि हुई)।
• मैं रूप में मानकों के साथ प्रत्यक्ष प्रश्नों की कोशिश की है: पैरामीटर। मेरी क्वेरी के बहुत शुरुआती संस्करण जो अधिक सरल थे, सीधे पूछताछ के लिए ठीक काम करते थे, लेकिन यह एक निश्चित जटिलता की तरह लग रहा था, क्वेरी एसएसआरएस से हमेशा के लिए लेना शुरू कर देगी।
• मैं तो एक सपा कि एक टेबल या वैश्विक अस्थायी तालिका में क्वेरी परिणाम सम्मिलित करता है को क्रियान्वित करने लगे। इससे थोड़ी देर के लिए मदद मिली, मुझे सीधे पूछताछ की तुलना में आगे बढ़ने में मदद मिली, लेकिन फिर से, यह लगभग बढ़ी हुई क्वेरी जटिलता या लंबाई की तरह लग रहा है, अंततः इस विधि को तोड़ दिया। नोट: तालिका-पॉपुलटिंग एसपी काम चल रहा है क्योंकि डेटासोर्स विकल्पों में चेक किए गए विकल्प "एकल लेनदेन का उपयोग करें" के साथ, डेटासेट को तब rdl फ़ाइल में उनकी उपस्थिति के क्रम में चलाया जाता है। डेटासेट जो कोई फ़ील्ड नहीं लौटाते हैं, तब तक चलते हैं, जब तक उनके सभी पैरामीटर संतुष्ट न हों।
• मैं सिर्फ एक टेबल लौटने समारोह की कोशिश की और यह अभी भी, कोई सुधार किया है, भले ही 1-5 सेकंड में SQL डेवलपर बदले में शाब्दिक मानकों के साथ सीधे कॉल।
सवाल आंकड़े नहीं है में डेटाबेस •। यह एक विक्रेता द्वारा बनाए गए उत्पाद का हिस्सा है और हमारे पास आंकड़े बनाने/अपडेट करने के लिए समय या प्रबंधन खरीदारी नहीं है। मैंने फ्लाई पर आंकड़ों की गणना करने के लिए डायनामिक_SAMPLING संकेत के साथ खेला और बेहतर निष्पादन योजना प्राप्त की: आंकड़ों के बिना लागत-आधारित अनुकूलक एक एचएएसएच जॉइन के बजाय लूप में शामिल होने का खराब इस्तेमाल कर रहा था, जिससे कई मिनट के निष्पादन के समय सामने आए। इस प्रकार मैंने प्रश्नों को शामिल करने के लिए पूछताछ संकेत दिए और रणनीतिक हैश में शामिल होने का कारण बनने के लिए, निष्पादन समय को केवल सेकंड में वापस लाया। मैं वापस नहीं गया और इन निष्पादन संकेतों का उपयोग करके एसएसआरएस में सीधे पूछताछ की कोशिश की।
• मुझे हमारे ओरेकल डीबीए से कुछ मदद मिली जिसने एक ट्रेस (या जो भी ओरेकल समकक्ष है) स्थापित किया और वह चीजों को चलाने में सक्षम था, लेकिन उसे अब तक कुछ भी उपयोगी नहीं मिला है। दुर्भाग्य से उनका समय सीमित है और हम वास्तव में यह पता लगाने में सक्षम नहीं हुए हैं कि सर्वर-पक्ष को क्या निष्पादित किया जा रहा है। मेरे पास ऐसा करने का अनुभव नहीं है या इस बारे में अध्ययन करने का समय मुझे यह कैसे करना है। क्या हो रहा है यह निर्धारित करने के लिए क्या करना है इसके बारे में सुझावों की सराहना की जाएगी।
मेरी केवल परिकल्पना कर रहे हैं:
क्वेरी • किसी भी तरह एक बुरा कार्य योजना लागू हो रही है। उदाहरण के लिए, कुछ हज़ारों की बजाय हजारों "बाएं" या बाहरी-लूप पंक्तियों के दौरान HASH में शामिल होने के बजाय अनुचित रूप से एक LOOP शामिल होने का उपयोग करें।
• एसएसआरएस पैरामीटर को nvarchar (4000) या कुछ उचित के बजाय कुछ सबमिट कर सकता है, और ओरेकल एसपी & फ़ंक्शन पैरामीटर के पास लंबाई विनिर्देश नहीं हैं लेकिन क्वेरी कॉल से उनकी निष्पादन लंबाई प्राप्त होती है, फिर कुछ प्रक्रिया क्योंकि पैरामीटर स्नीफिंग पिछले बिंदु के रूप में निष्पादन योजना को गड़बड़ कर रहा है।
• प्रश्न किसी भी तरह एसएसआरएस/प्रदाता द्वारा पुनः लिखा जा रहा है। मैं एक बहु-मूल्यवान पैरामीटर का उपयोग कर रहा हूं, लेकिन जैसा नहीं है: पैरामीटर अभिव्यक्ति के रूप में सबमिट किया जा रहा है (पैरामीटर्स! मल्टीवैल्यूड पैरामीटर। वैल्यू, ",") इसलिए इसे किसी भी पुनर्लेखन की आवश्यकता नहीं है। बस एक साधारण बाध्यकारी और जमा करने। मैं नहीं देखता कि यह एसपी और फ़ंक्शन कॉल में कैसे सच हो सकता है, लेकिन भगवान, यह और क्या हो सकता है?
मुझे एहसास है कि यह एक बहुत ही जटिल और लंबी क्वेरी है, लेकिन यह वही है जो मुझे चाहिए। यह कितना डेटा पूछता है इस पर निर्भर करता है कि यह 1-5 सेकंड में चलता है। जटिलता के कारणों में से कुछ हैं:
- ठीक से अल्पविराम से अलग लागत केंद्र सूची पैरामीटर
- की अनुमति दे साप्ताहिक टूटने वैकल्पिक होने के लिए और यदि शामिल है, एक महीने में सभी सप्ताह सुनिश्चित भले ही दिखाए जाते हैं निपटने उनके लिए कोई डेटा नहीं है।
- उपयुक्त होने पर "कोई चालान" नहीं दिखा रहा है।
- सारांश महीनों की एक परिवर्तनीय संख्या की अनुमति।
- वैकल्पिक वाईटीडी कुल होने के बाद।
- पिछले/ऐतिहासिक तुलना डेटा सहित इसका मतलब है कि मैं इस महीने के विक्रेताओं का उपयोग नहीं कर सकता, मुझे किसी भी ऐतिहासिक कॉलम में सभी विक्रेताओं को दिखाना होगा।
वैसे भी, यहां क्वेरी है, एसपी संस्करण (हालांकि मुझे नहीं लगता कि यह बहुत मददगार होगा)।
create or replace
PROCEDURE VendorInvoiceSummary (
FromDate IN date,
ToDate IN date,
CostCenterList IN varchar2,
IncludeWeekly IN varchar2,
ComparisonMonths IN number,
IncludeYTD IN varchar2
)
AS
BEGIN
INSERT INTO InvoiceSummary (Mo, CostCenter, Vendor, VendorName, Section, TimeUnit, Amt)
SELECT
Mo,
CostCenter,
Vendor,
VendorName,
Section,
TimeUnit,
Amt
FROM (
WITH CostCenters AS (
SELECT Substr(REGEXP_SUBSTR(CostCenterList, '[^,]+', 1, LEVEL) || ' ', 1, 15) CostCenter
FROM DUAL
CONNECT BY LEVEL <= Length(CostCenterList) - Length(Replace(CostCenterList, ',', '')) + 1
), Invoices AS (
SELECT /*+ORDERED USE_HASH(D)*/
TRUNC(I.Invoice_Dte, 'YYYY') Yr,
TRUNC(I.Invoice_Dte, 'MM') Mo,
D.Dis_Acct_Unit CostCenter,
I.Vendor,
V.Vendor_VName,
CASE
WHEN I.Invoice_Dte >= FromDate AND I.Invoice_Dte < ToDate
THEN (TRUNC(I.Invoice_Dte, 'W') - TRUNC(I.Invoice_Dte, 'MM'))/7 + 1
ELSE 0
END WkNum,
Sum(D.To_Base_Amt) To_Base_Amt
FROM
ICCompany C
INNER JOIN APInvoice I
ON C.Company = I.Company
INNER JOIN APDistrib D
ON C.Company = D.Company
AND I.Invoice = D.Invoice
AND I.Vendor = D.Vendor
AND I.Suffix = D.Suffix
INNER JOIN CostCenters CC
ON D.Dis_Acct_Unit = CC.CostCenter
INNER JOIN APVenMast V ON I.Vendor = V.Vendor
WHERE
D.Cancel_Seq = 0
AND I.Cancel_Seq = 0
AND I.Invoice_Dte >= Least(ADD_MONTHS(FromDate, -ComparisonMonths), TRUNC(FromDate, 'YYYY'))
AND I.Invoice_Dte < ToDate
AND V.Vendor_Group = '1 ' -- index help
GROUP BY
TRUNC(I.Invoice_Dte, 'YYYY'),
TRUNC(I.Invoice_Dte, 'MM'),
D.Dis_Acct_Unit,
I.Vendor,
V.Vendor_VName,
CASE
WHEN I.Invoice_Dte >= FromDate AND I.Invoice_Dte < ToDate
THEN (TRUNC(I.Invoice_Dte, 'W') - TRUNC(I.Invoice_Dte, 'MM'))/7 + 1
ELSE 0
END
), Months AS (
SELECT ADD_MONTHS(Least(ADD_MONTHS(FromDate, -ComparisonMonths), TRUNC(FromDate, 'YYYY')), LEVEL - 1) Mo
FROM DUAL
CONNECT BY LEVEL <= MONTHS_BETWEEN(ToDate, Least(ADD_MONTHS(FromDate, -ComparisonMonths), TRUNC(FromDate, 'YYYY')))
), Sections AS (
SELECT 1 Section, 1 StartUnit, 5 EndUnit FROM DUAL
UNION ALL SELECT 2, 0, ComparisonMonths FROM DUAL
UNION ALL SELECT 3, 1, 1 FROM DUAL WHERE IncludeYTD = 'Y'
), Vals AS (
SELECT LEVEL - 1 TimeUnit
FROM DUAL
CONNECT BY LEVEL <= (SELECT Max(EndUnit) FROM Sections) + 1
), TimeUnits AS (
SELECT S.Section, V.TimeUnit
FROM
Sections S
INNER JOIN Vals V
ON V.TimeUnit BETWEEN S.StartUnit AND S.EndUnit
), Names AS (
SELECT DISTINCT
M.Mo,
Coalesce(I.Vendor, '0') Vendor,
Coalesce(I.Vendor_VName, 'No Paid Invoices') Vendor_VName,
Coalesce(I.CostCenter, ' ') CostCenter
FROM
Months M
LEFT JOIN Invoices I
ON Least(ADD_MONTHS(M.Mo, -ComparisonMonths), TRUNC(M.Mo, 'YYYY')) < I.Mo
AND M.Mo >= I.Mo
WHERE
M.Mo >= FromDate
AND M.Mo < ToDate
)
SELECT
N.Mo,
N.CostCenter,
N.Vendor,
N.Vendor_VName VendorName,
T.Section,
T.TimeUnit,
Sum(I.To_Base_Amt) Amt
FROM
Names N
CROSS JOIN TimeUnits T
LEFT JOIN Invoices I
ON N.CostCenter = I.CostCenter
AND N.Vendor = I.Vendor
AND (
(
T.Section = 1 -- Weeks for current month
AND N.Mo = I.Mo
AND T.TimeUnit = I.WkNum
) OR (
T.Section = 2 -- Summary months
AND ADD_MONTHS(N.Mo, -T.TimeUnit) = I.Mo
) OR (
T.Section = 3 -- YTD
AND I.Mo BETWEEN TRUNC(N.Mo, 'YYYY') AND N.Mo
)
)
WHERE
N.Mo >= FromDate
AND N.Mo < ToDate
AND NOT (-- Only 4 weeks when a month is less than 28 days long
T.Section = 2
AND T.TimeUnit = 5
AND TRUNC(N.Mo + 28, 'MM') <> N.Mo
AND I.CostCenter IS NULL
) AND (
T.Section <> 1
OR IncludeWeekly = 'Y'
)
GROUP BY
N.Mo,
N.CostCenter,
N.Vendor,
N.Vendor_VName,
T.Section,
T.TimeUnit
) X;
COMMIT;
END;
अद्यतन
यहां तक कि (मेरे एसक्यूएल सर्वर ज्ञान का अनुवाद करने में) सब के बारे में ओरेकल निष्पादन योजनाओं और संकेत सीखने के बाद, मैं अभी भी जब तक मैं इसे चलाने बनाया SSRS में जल्दी से चलाने के लिए क्वेरी नहीं मिल सका दो चरणों में, वास्तविक तालिका परिणामों को GLOBAL TEMPORARY TABLE
में डाल दें और फिर उस से डेटा निकालने के लिए दूसरा। DYNAMIC_SAMPLING
ने मुझे एक अच्छा निष्पादन योजना दी, जिसे मैंने तब शामिल होने और संकेतों का उपयोग करके कॉपी किया। यहां अंतिम एसपी है (यह एक फ़ंक्शन नहीं हो सकता है क्योंकि ओरेकल में आप किसी फ़ंक्शन में डीएमएल नहीं कर सकते हैं जब उस फ़ंक्शन को SELECT स्टेटमेंट के अंदर बुलाया जाता है):
कभी-कभी मैं कसम खाता हूं कि यह मेरे शामिल संकेतों को अनदेखा कर रहा था swap_join_inputs
और no_swap_join_inputs
लेकिन मेरे पढ़ने से जाहिर है ओरेकल केवल संकेतों को अनदेखा करता है जब उनका वास्तव में उपयोग नहीं किया जा सकता है या आप कुछ गलत कर रहे हैं। सौभाग्य से, टेबल उचित रूप से बदल गए (जैसा कि USE_NL(CC)
के मामले में यह विश्वसनीय रूप से सीसी तालिका को स्वैप, बाएं इनपुट के रूप में रखता है, भले ही यह आखिरी बार शामिल हो)।
CREATE OR REPLACE
PROCEDURE VendorInvoicesSummary (
FromDate IN date,
ToDate IN date,
CostCenterList IN varchar2,
IncludeWeekly IN varchar2,
ComparisonMonths IN number,
IncludeYTD IN varchar2
)
AS
BEGIN
INSERT INTO InvoiceTemp (Yr, Mo, CostCenter, Vendor, WkNum, Amt) -- A global temporary table
SELECT /*+LEADING(C I D CC) USE_HASH(I D) USE_NL(CC)*/
TRUNC(I.Invoice_Dte, 'YYYY') Yr,
TRUNC(I.Invoice_Dte, 'MM') Mo,
D.Dis_Acct_Unit CostCenter,
I.Vendor,
CASE
WHEN I.Invoice_Dte >= FromDate AND I.Invoice_Dte < ToDate
THEN (TRUNC(I.Invoice_Dte, 'W') - TRUNC(I.Invoice_Dte, 'MM'))/7 + 1
ELSE 0
END WkNum,
Sum(D.To_Base_Amt) To_Base_Amt
FROM
ICCompany C
INNER JOIN APInvoice I
ON C.Company = I.Company
INNER JOIN APDistrib D
ON C.Company = D.Company
AND I.Invoice = D.Invoice
AND I.Vendor = D.Vendor
AND I.Suffix = D.Suffix
INNER JOIN (
SELECT Substr(REGEXP_SUBSTR(CostCenterList, '[^,]+', 1, LEVEL) || ' ', 1, 15) CostCenter
FROM DUAL
CONNECT BY LEVEL <= Length(CostCenterList) - Length(Replace(CostCenterList, ',', '')) + 1
) CC ON D.Dis_Acct_Unit = CC.CostCenter
WHERE
D.Cancel_Seq = 0
AND I.Cancel_Seq = 0
AND I.Invoice_Dte >= Least(ADD_MONTHS(FromDate, -ComparisonMonths), TRUNC(FromDate, 'YYYY'))
AND I.Invoice_Dte < ToDate
GROUP BY
TRUNC(I.Invoice_Dte, 'YYYY'),
TRUNC(I.Invoice_Dte, 'MM'),
D.Dis_Acct_Unit,
I.Vendor,
CASE
WHEN I.Invoice_Dte >= FromDate AND I.Invoice_Dte < ToDate
THEN (TRUNC(I.Invoice_Dte, 'W') - TRUNC(I.Invoice_Dte, 'MM'))/7 + 1
ELSE 0
END;
INSERT INTO InvoiceSummary (Mo, CostCenter, Vendor, VendorName, Section, TimeUnit, Amt)
SELECT
Mo,
CostCenter,
Vendor,
VendorName,
Section,
TimeUnit,
Amt
FROM (
WITH Months AS (
SELECT ADD_MONTHS(Least(ADD_MONTHS(FromDate, -ComparisonMonths), TRUNC(FromDate, 'YYYY')), LEVEL - 1) Mo
FROM DUAL
CONNECT BY LEVEL <= MONTHS_BETWEEN(ToDate, Least(ADD_MONTHS(FromDate, -ComparisonMonths), TRUNC(FromDate, 'YYYY')))
), Sections AS (
SELECT 1 Section, 1 StartUnit, 5 EndUnit FROM DUAL
UNION ALL SELECT 2, 0, ComparisonMonths FROM DUAL
UNION ALL SELECT 3, 1, 1 FROM DUAL WHERE IncludeYTD = 'Y'
), Vals AS (
SELECT LEVEL - 1 TimeUnit
FROM DUAL
CONNECT BY LEVEL <= (SELECT Max(EndUnit) FROM Sections) + 1
), TimeUnits AS (
SELECT S.Section, V.TimeUnit
FROM
Sections S
INNER JOIN Vals V
ON V.TimeUnit BETWEEN S.StartUnit AND S.EndUnit
), Names AS (
SELECT DISTINCT
M.Mo,
Coalesce(I.Vendor, '0') Vendor,
Coalesce(I.CostCenter, ' ') CostCenter
FROM
Months M
LEFT JOIN InvoiceTemp I
ON Least(ADD_MONTHS(M.Mo, -ComparisonMonths), TRUNC(M.Mo, 'YYYY')) <= I.Mo
AND I.Mo <= M.Mo
WHERE
M.Mo >= FromDate
AND M.Mo < ToDate
)
SELECT
N.Mo,
N.CostCenter,
N.Vendor,
Coalesce(V.Vendor_VName, 'No Paid Invoices') VendorName,
T.Section,
T.TimeUnit,
Sum(I.Amt) Amt
FROM
Names N
INNER JOIN APVenMast V ON N.Vendor = V.Vendor
CROSS JOIN TimeUnits T
LEFT JOIN InvoiceTemp I
ON N.CostCenter = I.CostCenter
AND N.Vendor = I.Vendor
AND (
(
T.Section = 1 -- Weeks for current month
AND N.Mo = I.Mo
AND T.TimeUnit = I.WkNum
) OR (
T.Section = 2 -- Summary months
AND ADD_MONTHS(N.Mo, -T.TimeUnit) = I.Mo
) OR (
T.Section = 3 -- YTD
AND I.Mo BETWEEN TRUNC(N.Mo, 'YYYY') AND N.Mo
)
)
WHERE
N.Mo >= FromDate
AND N.Mo < ToDate
AND V.Vendor_Group = '1 '
AND NOT (-- Only 4 weeks when a month is less than 28 days long
T.Section = 2
AND T.TimeUnit = 5
AND TRUNC(N.Mo + 28, 'MM') <> N.Mo
AND I.CostCenter IS NULL
) AND (
T.Section <> 1
OR IncludeWeekly = 'Y'
)
GROUP BY
N.Mo,
N.CostCenter,
N.Vendor,
V.Vendor_VName,
T.Section,
T.TimeUnit
) X;
COMMIT;
END;
यह एक लंबे, दर्दनाक सवारी कर दिया गया है, लेकिन एक बात मैंने सीखा है वहाँ अगर यह है कि ठीक से अपडेट किए गए आँकड़ों के बिना एक डेटाबेस में काम कर रहा है (जो मैं भी जोड़ने के लिए हमारे डीबीए हो रही गौर करने के लिए जा रहा हूँ है हालांकि विक्रेता उनके बारे में परवाह नहीं करता है) किसी ऐसे व्यक्ति के लिए वास्तविक आपदा हो सकता है जो उचित समय में काम करना चाहता है।
क्या आपके आंकड़े अद्यतित हैं? –
नहीं, जैसा कि मैंने कहा था कि विक्रेता आंकड़ों का उपयोग नहीं करता है। वे इस डीबी में प्रत्येक क्वेरी के लिए नियम-आधारित होते हैं जिसमें प्राचीन उत्पत्ति होती है। – ErikE