Oracle
 sql >> डेटाबेस >  >> RDS >> Oracle

क्या COUNT(पंक्तिबद्ध) COUNT(*) से तेज़ है?

Oracle मंचों और समाचार समूहों में एक लंबे समय से चली आ रही चर्चा किसी तालिका से एक पंक्ति गणना वापस करने के लिए गिनती (*) का उपयोग करने की दक्षता रही है। उस चर्चा में एक नई शिकन अब गिनती (पंक्तिबद्ध) को अधिक कुशल विकल्प के रूप में पेश करती है; तर्क बताता है कि गिनती (*) पूरी कॉलम सूची का विस्तार करती है, जैसे "चयन * ...", और, जैसे, वांछित तालिका में सीएलओबी कॉलम मौजूद होने पर संसाधन सिंक हो सकता है। आइए उस तर्क को देखें और देखें कि क्या इसमें पानी है। आइए एक CLOB कॉलम वाली तालिका बनाकर और उसे पॉप्युलेट करके शुरू करें:

SQL>
SQL> create table count_test(
  2  id      number,
  3  val     varchar2(40),
  4  clb     clob);

Table created.

SQL>
SQL> begin
  2          for z in 1..1000000 loop
  3             insert into count_test
  4             values(z, 'Record '||z, 'Clob value '||z);
  5          end loop;
  6
  7          commit;
  8  end;
  9  /

PL/SQL procedure successfully completed.

SQL>

इसके बाद ऑप्टिमाइज़र ट्रेस को डंप करने के लिए ईवेंट 10053 सेट करें ताकि हम देख सकें कि Oracle कैसे काउंट () क्वेरीज़ को निष्पादित करने की योजना बना रहा है:

SQL> alter session set events = '10053 trace  name context forever, level 2';

Session altered.

चरण निर्धारित है, आइए गिनती () के कुछ प्रकारों को देखें कि ओरेकल कैसे व्यवहार करता है। सबसे पहले, हम एक सीधी गणना (*) निष्पादित करेंगे और योजना प्रदर्शित करेंगे:

SQL> select count(*) from count_test;

  COUNT(*)
----------
   1000000

SQL> alter session set events = '10053 trace name context off';

Session altered.

SQL> explain plan for select count(*) from count_test;

Explained.

SQL> select * from table(dbms_xplan.display(null,null,'projection'));

PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------------
Plan hash value: 371675025

----------------------------------------+-----------------------------------+
| Id  | Operation           | Name      | Rows  | Bytes | Cost  | Time      |
----------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT    |           |       |       |  3582 |           |
| 1   |  SORT AGGREGATE     |           |     1 |       |       |           |
| 2   |   TABLE ACCESS FULL | COUNT_TEST|  848K |       |  3582 |  00:00:43 |
----------------------------------------+-----------------------------------+      
Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]
   2 - (rowset=1019)

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

19 rows selected.

SQL>

उत्पन्न ट्रेस फ़ाइल को देखते हुए, Oracle परिणाम लौटाने के लिए बस काउंट (*) का उपयोग करता है:

Final query after transformations:******* UNPARSED QUERY IS *******
SELECT COUNT(*) "COUNT(*)" FROM "BING"."COUNT_TEST" "COUNT_TEST"          
...
----- Explain Plan Dump -----
----- Plan Table -----
============
Plan Table
============
----------------------------------------+-----------------------------------+
| Id  | Operation           | Name      | Rows  | Bytes | Cost  | Time      |
----------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT    |           |       |       |  3582 |           |
| 1   |  SORT AGGREGATE     |           |     1 |       |       |           |
| 2   |   TABLE ACCESS FULL | COUNT_TEST|  848K |       |  3582 |  00:00:43 |
----------------------------------------+-----------------------------------+                 
Query Block Name / Object Alias (identified by operation id):
------------------------------------------------------------
1 - SEL$1
2 - SEL$1                / "COUNT_TEST"@"SEL$1"
------------------------------------------------------------
Predicate Information:
------------------------

SQL>

वहाँ कोई आश्चर्य नहीं; ध्यान दें कि Oracle तालिका के सभी स्तंभों में "*" का विस्तार नहीं करता है - इस मामले में "*" इंगित करता है कि सभी पंक्तियों की गणना की जानी है। यदि वास्तविक कॉलम नाम प्रदान किया गया होता तो Oracle निर्दिष्ट कॉलम में मानों की गणना करता। आइए अब देखें कि Oracle गिनती (पंक्तिबद्ध) क्वेरी के साथ क्या करता है:

SQL> alter session set events = '10053 trace  name context forever, level 2';

Session altered.

SQL> select count(rowid) from count_test;

COUNT(ROWID)
------------
     1000000

SQL> alter session set events = '10053 trace name context off';

Session altered.

SQL> explain plan for select count(rowid) from count_test;

Explained.

SQL> select * from table(dbms_xplan.display(null,null,'projection'));

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------
Plan hash value: 371675025

----------------------------------------+-----------------------------------+
| Id  | Operation           | Name      | Rows  | Bytes | Cost  | Time      |
----------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT    |           |       |       |  3582 |           |
| 1   |  SORT AGGREGATE     |           |     1 |    12 |       |           |
| 2   |   TABLE ACCESS FULL | COUNT_TEST|  848K | 9941K |  3582 |  00:00:43 |
----------------------------------------+-----------------------------------+           

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(ROWID)[22]
   2 - (rowset=256) ROWID[ROWID,10]

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

19 rows selected.

SQL>

Oracle तालिका में प्रत्येक पंक्ति के लिए एक पंक्तिबद्ध मान उत्पन्न करता है, एक ऑपरेशन जो कुछ CPU संसाधनों का उपभोग करेगा। चूंकि काउंट (*) संस्करण के रूप में लगभग उसी समय में क्वेरी वापस आ गई थी, इसलिए प्रदर्शन 'हिट' नगण्य प्रतीत होता है। प्राथमिक कुंजी जोड़ने से योजनाएँ थोड़ी बदल जाती हैं लेकिन क्वेरी टेक्स्ट नहीं:


SQL> alter table count_test add constraint count_pk primary key(id);

Table altered.                                                                                                                            
SQL>
SQL> alter session set events = '10053 trace  name context forever, level 2';

Session altered.

SQL> select count(*) from count_test;

  COUNT(*)
----------
   1000000

SQL> alter session set events = '10053 trace name context off';

Session altered.

SQL> explain plan for select count(*) from count_test;

Explained.

SQL> select * from table(dbms_xplan.display(null,null,'projection'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------
Plan hash value: 371675025

--------------------------------------------------------------------------
| Id  | Operation             | Name     | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |          |     1 |   589   (2)| 00:00:01 |
|   1 |  SORT AGGREGATE       |          |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| COUNT_PK |   848K|   589   (2)| 00:00:01 |
--------------------------------------------------------------------------        

Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(*)[22]
   2 - (rowset=1019)

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

19 rows selected.

SQL>
SQL>
SQL> alter session set events = '10053 trace  name context forever, level 2';

Session altered.

SQL> select count(rowid) from count_test;

COUNT(ROWID)
------------
     1000000

SQL> alter session set events = '10053 trace name context off';

Session altered.

SQL> explain plan for select count(rowid) from count_test;

Explained.

SQL> select * from table(dbms_xplan.display(null,null,'projection'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------
Plan hash value: 371675025

----------------------------------------------------------------------------------
| Id  | Operation             | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |          |     1 |    12 |   589   (2)| 00:00:01 |
|   1 |  SORT AGGREGATE       |          |     1 |    12 |            |          |
|   2 |   INDEX FAST FULL SCAN| COUNT_PK |   848K|  9941K|   589   (2)| 00:00:01 |
----------------------------------------------------------------------------------                 
Column Projection Information (identified by operation id):
-----------------------------------------------------------

   1 - (#keys=0) COUNT(ROWID)[22]
   2 - (rowset=256) ROWID[ROWID,10]

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

19 rows selected.

SQL>
SQL> spool off
commit;

प्राथमिक कुंजी जोड़ने के बाद 10053 ट्रेस विवरण नहीं बदला।

ऐसा प्रतीत होता है कि इस प्रयोग से जानकारी के दो टुकड़े एकत्र किए गए हैं - गिनती (पंक्तिबद्ध) गिनती (*) से बेहतर नहीं है जब तालिकाओं में सीएलओबी कॉलम होते हैं और गिनती (*) कॉलम सूची का विस्तार नहीं करती है क्योंकि "चयन *" करता है (और यह मानने का कोई कारण नहीं है कि यह होना चाहिए)।

प्रमाण पुडिंग में है, जैसा कि पुरानी कहावत है।

# # #

डेविड फिट्ज़जारेल . के लेख देखें


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. IF EXISTS स्थिति PLSQL के साथ काम नहीं कर रही है

  2. 11i/R12 . में बहु भाषा समर्थन

  3. Oracle में नंबर को स्ट्रिंग में कैसे बदलें?

  4. postgreSQL mysql oracle मतभेद

  5. वास्तविक Oracle SQL स्टेटमेंट को कैसे देखें जिसे निष्पादित किया जा रहा है