sql - tables - outer join شرح



سكل للبحث عن إدخالات مكررة(ضمن مجموعة) (5)

سكل للبحث عن إدخالات مكررة (ضمن مجموعة)

لدي مشكلة صغيرة وأنا لست متأكدا ما سيكون أفضل وسيلة لإصلاحه، وأنا فقط الوصول المحدود إلى قاعدة البيانات (أوراكل) نفسها. في جدولنا "إيفنت" لدينا حوالي 160k إدخالات، كل إيفنت لديه غروبيد وإدخال عادي لديه بالضبط 5 صفوف مع نفس غروبيد. بسبب خلل نحصل حاليا على اثنين من إدخالات مكررة (مكررة، لذلك 10 صفوف بدلا من 5، مجرد إيفنتيد مختلفة.هذا قد يتغير، لذلك فقط <> 5). نحن بحاجة إلى تصفية جميع إدخالات هذه المجموعات.

بسبب محدودية الوصول إلى قاعدة البيانات لا يمكننا استخدام جدول مؤقت، ولا يمكننا إضافة فهرس إلى العمود غروبيد لجعله أسرع.

يمكننا الحصول على غروبيدس مع هذا الاستعلام، ولكننا بحاجة إلى استعلام ثان للحصول على البيانات المطلوبة

select A."GROUPID"
from "EVENT" A
group by A."GROUPID"
having count(A."GROUPID") <> 5

وأحد الحلول سيكون اختيارا فرعيا:

select *
from "EVENT" A
where A."GROUPID" IN (
  select B."GROUPID"
  from "EVENT" B
  group by B."GROUPID"
  having count(B."GROUPID") <> 5
)

بدون فهرس على غروبيد و 160k الإدخالات، وهذا يستغرق وقتا طويلا جدا. حاول التفكير في الانضمام التي يمكن التعامل مع هذا، ولكن لا يمكن العثور على حل جيد حتى الآن.

يمكن لأي شخص أن يجد حلا جيدا لهذا ربما؟

تعديل صغير: ليس لدينا نسخ مكررة بنسبة 100٪ هنا، حيث لا يزال لكل إدخال معرف فريد، كما أن غروب ليست فريدة من نوعها (ولهذا السبب نحتاج إلى استخدام "مجموعة حسب") - أو ربما أفتقد مجرد حل سهل إيت :)

مثال صغير حول البيانات (لا أريد حذفه، فقط العثور عليه)

EVENTID | GROUPID | TYPEID
123456 123 12
123457 123 145
123458 123 2612
123459 123 41
123460 123 238

234567 123 12
234568 123 145
234569 123 2612
234570 123 41
234571 123 238

لديها بعض الأعمدة أكثر، مثل الطابع الزمني الخ، ولكن كما ترون بالفعل، كل شيء متطابقة، إلى جانب إيفنتيد.

ونحن سوف تشغيله في كثير من الأحيان للاختبار، للعثور على علة والتحقق مما إذا كان يحدث مرة أخرى.

https://src-bin.com


Answer #1

إذا لم تقم أدوار ديسيبلز الخاصة بك بإضافة فهرس لإجراء ذلك بشكل أسرع، فاطلب منهم ما يقترحونه (وهذا ما يدفعونه مقابل كل شيء). ويفترض أن يكون لديك حالة عمل لماذا كنت بحاجة إلى هذه المعلومات في هذه الحالة يجب أن تكون إدارتك الفورية إلى جانبكم.

ربما يمكنك أن تطلب من ديسيبلز الخاص بك تكرار البيانات في قاعدة بيانات حيث يمكنك إضافة فهرس.


Answer #2

كم يستغرق ذلك سكل فعلا؟ أنت ذاهب فقط لتشغيله بمجرد أن أفترض، بعد إصلاح الخلل الذي تسبب في الفساد في المقام الأول؟ أنا مجرد إعداد حالة اختبار مثل هذا:

SQL> create table my_objects as 
  2  select object_name, ceil(rownum/5) groupid, rpad('x',500,'x') filler
  3  from all_objects;

Table created.

SQL> select count(*) from my_objects;

  COUNT(*)
----------
     83782

SQL> select * from my_objects where groupid in (
  2  select groupid from my_objects
  3  group by groupid
  4  having count(*) <> 5
  5  );

OBJECT_NAME                       GROUPID FILLER
------------------------------ ---------- --------------------------------
XYZ                                 16757 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
YYYY                                16757 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Elapsed: 00:00:01.67

أقل من ثانيتين. حسنا، الجدول الخاص بي لديه نصف العديد من الصفوف كما لك، ولكن 160K ليست ضخمة. أضفت عمود حشو لجعل الجدول يستغرق بعض مساحة القرص. كانت خطة تنفيذ أوتوتريس:

-------------------------------------------------------------------------
| Id  | Operation             | Name       | Rows  | Bytes | Cost (%CPU)|
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |            |   389 |   112K| 14029   (2)|
|*  1 |  HASH JOIN            |            |   389 |   112K| 14029   (2)|
|   2 |   VIEW                | VW_NSO_1   | 94424 |  1198K|  6570   (2)|
|*  3 |    FILTER             |            |       |       |            |
|   4 |     HASH GROUP BY     |            |     1 |  1198K|  6570   (2)|
|   5 |      TABLE ACCESS FULL| MY_OBJECTS | 94424 |  1198K|  6504   (1)|
|   6 |   TABLE ACCESS FULL   | MY_OBJECTS | 94424 |    25M|  6506   (1)|
-------------------------------------------------------------------------

Answer #3

مشكلة كلاسيكية للاستفسارات التحليلية لحلها:

select eventid,
       groupid,
       typeid
from   (
       Select eventid,
              groupid,
              typeid,
              count(*) over (partition by group_id) count_by_group_id
       from   EVENT
       )
where count_by_group_id <> 5

Answer #4

من منظور سكل أعتقد أنك قد أجبت بالفعل سؤالك الخاص. النهج الذي وصفته (أي باستخدام الاختيار الفرعي) على ما يرام، وسأكون مندهشا إذا اختلفت أي طريقة أخرى لكتابة الاستعلام بشكل كبير في الأداء.

160K السجلات لا يبدو مثل الكثير بالنسبة لي. يمكن أن أفهم إذا كنت غير راض عن أداء هذا الاستعلام إذا كان الذهاب إلى قطعة من رمز التطبيق، ولكن من أصوات ذلك كنت مجرد استخدامه كجزء من بعض البيانات تطهير إكسيرسيس. (وهكذا نتوقع منك أن تكون أكثر تسامحا قليلا في الأداء).

حتى من دون أي مؤشر دعم، لا يزال اثنين فقط الجدول الجدول الكامل بمسح على 160K الصفوف، والتي بصراحة، كنت أتوقع أن أداء في نوع من الوقت المعقول غامضة.

التحدث مع المسؤولين ديسيبل الخاص بك. لقد ساعدت في خلق المشكلة، لذلك السماح لهم أن يكونوا جزءا من الحل.

/ إديت / في هذه الأثناء، قم بتشغيل الاستعلام لديك. معرفة كم من الوقت يستغرق، بدلا من التخمين. حتى أفضل سيكون لتشغيله، مع أوتوتريس مجموعة على، ونشر النتائج هنا، فإننا قد تكون قادرة على مساعدتك على صقل ذلك إلى حد ما.


Answer #5

يمكنك الحصول على الجواب مع الانضمام بدلا من الاستعلام الفرعي

select
    a.*
from
    event as a
inner join
    (select groupid
     from event
     group by groupid
     having count(*) <> 5) as b
  on a.groupid = b.groupid

هذه طريقة شائعة إلى حد ما للحصول على جميع المعلومات من الصفوف في المجموعة.

مثل إجابتك المقترحة والردود الأخرى، سيتم تشغيل هذا بشكل أسرع بكثير مع فهرس على غروبيد. والامر متروك لدبا لتحقيق التوازن بين فائدة جعل الاستعلام الخاص بك تشغيل أسرع بكثير مقابل تكلفة الحفاظ على مؤشر آخر.

إذا قرر دبا ضد الفهرس، تأكد من أن الأشخاص المناسبين يفهمون أن إستراتيجية الفهرس وليس الطريقة التي كتبت بها الاستعلام الذي يبطئ الأمور.





join