पर उच्च प्रदर्शन दृष्टिकोण मैं मांग पर त्वरित रूप से चल रहे रिग्रेशन के लिए एक आधारभूत संरचना बनाने का प्रयास कर रहा हूं, जो हमारे वेबसर्वर पर सभी ऐतिहासिक गतिविधियों वाले डेटाबेस से अपाचे अनुरोधों को खींच रहा है। यह सुनिश्चित करके कवरेज में सुधार करने के लिए कि हम अभी भी अपने छोटे ग्राहकों से अनुरोधों को वापस लेते हैं, मैं प्रत्येक ग्राहक के लिए अनुरोधों को अधिकतर प्राप्त करने के लिए अनुरोधों का वितरण सुनिश्चित करना चाहता हूं (इस प्रश्न के लिए, 10 कहें)।सबसे बड़ी-एन-प्रति-समूह एसक्यूएल क्वेरी
मुझे यहां कई समान प्रश्नों का उत्तर मिला, जिनमें से सबसे नज़दीक SQL query to return top N rows per ID across a range of IDs प्रतीत होता था, लेकिन उत्तर अधिकांश भाग प्रदर्शन-अज्ञेय समाधान के लिए थे जो मैंने पहले ही कोशिश की थी।
SELECT
*
FROM
(
SELECT
dailylogdata.*,
row_number() over (partition by dailylogdata.contextid order by occurrencedate) rn
FROM
dailylogdata
WHERE
shorturl in (?)
)
WHERE
rn <= 10;
हालांकि यह देखते हुए कि इस तालिका किसी दिए गए दिन के लिए प्रविष्टियों के लाखों लोगों में शामिल है, और इस दृष्टिकोण से सभी पंक्तियों को पढ़ने जरूरी: उदाहरण के लिए, ROW_NUMBER() विश्लेषणात्मक समारोह से हम बिलकुल डेटा हम के लिए देख रहे हो जाता है सूचकांक जो row_number विश्लेषणात्मक फ़ंक्शन को लागू करने के लिए हमारे चयन मानदंड से मेल खाता है, प्रदर्शन भयानक है। हम अंत में लगभग दस लाख पंक्तियों का चयन, केवल बाहर उनमें से अधिकांश फेंकने के लिए है क्योंकि उनके ROW_NUMBER ऊपर क्वेरी को क्रियान्वित करने से 10 आँकड़े को पार कर:
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | Writes | OMem | 1Mem | Used-Mem | Used-Tmp||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|| 0 | SELECT STATEMENT | | 1 | | 12222 |00:09:08.94 | 895K| 584K| 301 | | | | ||
||* 1 | VIEW | | 1 | 4427K| 12222 |00:09:08.94 | 895K| 584K| 301 | | | | ||
||* 2 | WINDOW SORT PUSHED RANK | | 1 | 4427K| 13536 |00:09:08.94 | 895K| 584K| 301 | 2709K| 743K| 97M (1)| 4096 ||
|| 3 | PARTITION RANGE SINGLE | | 1 | 4427K| 932K|00:22:27.90 | 895K| 584K| 0 | | | | ||
|| 4 | TABLE ACCESS BY LOCAL INDEX ROWID| DAILYLOGDATA | 1 | 4427K| 932K|00:22:27.61 | 895K| 584K| 0 | | | | ||
||* 5 | INDEX RANGE SCAN | DAILYLOGDATA_URLCONTEXT | 1 | 17345 | 932K|00:00:00.75 | 1448 | 0 | 0 | | | | ||
|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |
|Predicate Information (identified by operation id): |
|--------------------------------------------------- |
| |
| 1 - filter("RN"<=:SYS_B_2) |
| 2 - filter(ROW_NUMBER() OVER (PARTITION BY "DAILYLOGDATA"."CONTEXTID" ORDER BY "OCCURRENCEDATE")<=:SYS_B_2) |
| 5 - access("SHORTURL"=:P1) |
| |
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
हालांकि, अगर बजाय हम केवल पहले 10 परिणाम के लिए क्वेरी इस क्वेरी को चलने से
SELECT
*
FROM
(
SELECT
dailylogdata.*
FROM
dailylogdata
WHERE
shorturl in (?)
and contextid = ?
)
WHERE
rownum <= 10;
आँकड़े:: एक विशिष्ट contextid के लिए, हम इस नाटकीय रूप से तेजी से निष्पादित कर सकते हैं
|-------------------------------------------------------------------------------------------------------------------------|
|| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers ||
|-------------------------------------------------------------------------------------------------------------------------|
|| 0 | SELECT STATEMENT | | 1 | | 10 |00:00:00.01 | 14 ||
||* 1 | COUNT STOPKEY | | 1 | | 10 |00:00:00.01 | 14 ||
|| 2 | PARTITION RANGE SINGLE | | 1 | 10 | 10 |00:00:00.01 | 14 ||
|| 3 | TABLE ACCESS BY LOCAL INDEX ROWID| DAILYLOGDATA | 1 | 10 | 10 |00:00:00.01 | 14 ||
||* 4 | INDEX RANGE SCAN | DAILYLOGDATA_URLCONTEXT | 1 | 1 | 10 |00:00:00.01 | 5 ||
|-------------------------------------------------------------------------------------------------------------------------|
| |
|Predicate Information (identified by operation id): |
|--------------------------------------------------- |
| |
| 1 - filter(ROWNUM<=10) |
| 4 - access("SHORTURL"=:P1 AND "CONTEXTID"=TO_NUMBER(:P2)) |
| |
+-------------------------------------------------------------------------------------------------------------------------+
इस उदाहरण में, ओरेकल चालाक है 10 परिणाम प्राप्त करने के बाद डेटा पुनर्प्राप्त करना बंद करने के लिए पर्याप्त है। I संदर्भों का एक पूरा सेट इकट्ठा कर सकता है और प्रोग्रामिक रूप से एक क्वेरी उत्पन्न करता है जिसमें प्रत्येक संदर्भ के लिए इस क्वेरी के एक उदाहरण और union all
पूरी गड़बड़ी होती है, लेकिन संदर्भित संख्याओं को देखते हुए, हम आंतरिक ओरेकल सीमा में भाग ले सकते हैं, और भले ही नहीं, यह दृष्टिकोण kludge reeks।
क्या किसी को ऐसे प्रश्न के बारे में पता है जो पहली क्वेरी की सादगी को बनाए रखता है, जबकि दूसरी क्वेरी के साथ प्रदर्शन को बनाए रखने के दौरान? यह भी ध्यान रखें कि मुझे वास्तव में पंक्तियों के स्थिर सेट को पुनर्प्राप्त करने की परवाह नहीं है; जब तक वे मेरे मानदंडों को पूरा करते हैं, वे एक रिग्रेशन के प्रयोजनों के लिए ठीक हैं।
संपादित करें: एडम मशच के सुझाव ने चाल की। मैं यहां अपने परिवर्तनों के साथ प्रदर्शन परिणामों को जोड़ रहा हूं क्योंकि मैं उनके जवाब के लिए टिप्पणी प्रतिक्रिया में फिट नहीं हो सकता। मैं भी इस बार के परीक्षण के लिए एक बड़ा डेटा सेट का उपयोग कर रहा है, यहाँ तुलना के लिए अपने मूल ROW_NUMBER दृष्टिकोण से (कैश्ड) आँकड़े हैं:
|-------------------------------------------------------------------------------------------------------------------------------------------------|
|| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads | OMem | 1Mem | Used-Mem ||
|-------------------------------------------------------------------------------------------------------------------------------------------------|
|| 0 | SELECT STATEMENT | | 1 | | 12624 |00:00:22.34 | 1186K| 931K| | | ||
||* 1 | VIEW | | 1 | 1163K| 12624 |00:00:22.34 | 1186K| 931K| | | ||
||* 2 | WINDOW NOSORT | | 1 | 1163K| 1213K|00:00:21.82 | 1186K| 931K| 3036M| 17M| ||
|| 3 | TABLE ACCESS BY INDEX ROWID| TWTEST | 1 | 1163K| 1213K|00:00:20.41 | 1186K| 931K| | | ||
||* 4 | INDEX RANGE SCAN | TWTEST_URLCONTEXT | 1 | 1163K| 1213K|00:00:00.81 | 8568 | 0 | | | ||
|-------------------------------------------------------------------------------------------------------------------------------------------------|
| |
|Predicate Information (identified by operation id): |
|--------------------------------------------------- |
| |
| 1 - filter("RN"<=10) |
| 2 - filter(ROW_NUMBER() OVER (PARTITION BY "CONTEXTID" ORDER BY NULL)<=10) |
| 4 - access("SHORTURL"=:P1) |
+-------------------------------------------------------------------------------------------------------------------------------------------------+
मैं एडम के सुझाव थोड़ा नीचे उबलते की स्वतंत्रता लिया है; यहाँ संशोधित क्वेरी ...
select
*
from
twtest
where
rowid in (
select
rowid
from (
select
rowid,
shorturl,
row_number() over (partition by shorturl, contextid
order by null) rn
from
twtest
)
where rn <= 10
and shorturl in (?)
);
है ... और उसके (कैश्ड) मूल्यांकन से आंकड़े:
|--------------------------------------------------------------------------------------------------------------------------------------|
|| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem ||
|--------------------------------------------------------------------------------------------------------------------------------------|
|| 0 | SELECT STATEMENT | | 1 | | 12624 |00:00:01.33 | 19391 | | | ||
|| 1 | NESTED LOOPS | | 1 | 1 | 12624 |00:00:01.33 | 19391 | | | ||
|| 2 | VIEW | VW_NSO_1 | 1 | 1163K| 12624 |00:00:01.27 | 6770 | | | ||
|| 3 | HASH UNIQUE | | 1 | 1 | 12624 |00:00:01.27 | 6770 | 1377K| 1377K| 5065K (0)||
||* 4 | VIEW | | 1 | 1163K| 12624 |00:00:01.25 | 6770 | | | ||
||* 5 | WINDOW NOSORT | | 1 | 1163K| 1213K|00:00:01.09 | 6770 | 283M| 5598K| ||
||* 6 | INDEX RANGE SCAN | TWTEST_URLCONTEXT | 1 | 1163K| 1213K|00:00:00.40 | 6770 | | | ||
|| 7 | TABLE ACCESS BY USER ROWID| TWTEST | 12624 | 1 | 12624 |00:00:00.04 | 12621 | | | ||
|--------------------------------------------------------------------------------------------------------------------------------------|
| |
|Predicate Information (identified by operation id): |
|--------------------------------------------------- |
| |
| 4 - filter("RN"<=10) |
| 5 - filter(ROW_NUMBER() OVER (PARTITION BY "SHORTURL","CONTEXTID" ORDER BY NULL NULL)<=10) |
| 6 - access("SHORTURL"=:P1) |
| |
|Note |
|----- |
| - dynamic sampling used for this statement (level=2) |
| |
+--------------------------------------------------------------------------------------------------------------------------------------+
के रूप में विज्ञापित, हम केवल पूरी तरह से फिल्टर्ड पंक्तियों के लिए dailylogdata मेज तक पहुँच रहे हैं ।मुझे चिंतित है कि प्रतीत होता है कि अभी भी urlcontext अनुक्रमणिका का पूर्ण स्कैन कर रहा है, जो कि पंक्तियों की संख्या (1213 के) के आधार पर है, लेकिन यह देखते हुए कि यह केवल 6770 बफर का उपयोग कर रहा है (यह संख्या स्थिर भी है अगर मैं संदर्भ-विशिष्ट परिणामों की संख्या बढ़ाता हूं) यह भ्रामक हो सकता है।
क्या आपने अन्य तरीकों/प्रश्नों को आजमाया है जो एक ही परिणाम (अधिकतम-एन-प्रति-समूह) प्राप्त करते हैं? –
आपकी दूसरी क्वेरी को "पहली 10 पंक्तियां" नहीं मिलती हैं, यह केवल 10 पंक्तियां, अर्ध-यादृच्छिक रूप से प्राप्त होती है। इसे पहली क्वेरी के एक विभाजन के बराबर करने के लिए, आपको आंतरिक क्वेरी में 'ऑर्डर बाय' जोड़ना होगा। अधिकांश भाग के लिए – Allan
@ypercube मैंने इसी तरह के प्रदर्शन परिणामों के साथ अन्य विश्लेषणात्मक कार्यों की कोशिश की है। मैंने कुछ और गूढ़ सामानों की कोशिश की [जैसे] [http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions056.htm#sthref1389) फ़ंक्शन जो मुझे आवश्यकतानुसार कई पंक्तियों को वापस नहीं करेगा , लेकिन मैंने सोचा कि यह इस क्वेरी से बेहतर प्रदर्शन कर सकता है। अन्य विश्लेषणात्मक कार्यों की तरह, यह आवश्यकतानुसार इंडेक्स से अधिक स्कैन किया गया है, हालांकि। – Trevor