हैश क्लस्टर ओ (1) एक्सेस समय प्रदान कर सकते हैं, लेकिन ओ (1) बाधा प्रवर्तन समय नहीं। हालांकि, व्यवहार में हैश क्लस्टर का निरंतर एक्सेस समय नियमित बी-ट्री इंडेक्स के ओ (लॉग एन) एक्सेस समय से भी बदतर है। साथ ही, क्लस्टर को कॉन्फ़िगर करना अधिक कठिन होता है और कुछ कार्यों के लिए उनका स्केल अच्छा नहीं होता है।
हैश क्लस्टर बनाएं
drop table orders_cluster;
drop cluster cluster1;
create cluster cluster1
(
MerchantID number,
TransactionID varchar2(20)
)
single table hashkeys 10000; --This number is important, choose wisely!
create table orders_cluster
(
id number,
MerchantID number,
TransactionID varchar2(20)
) cluster cluster1(merchantid, transactionid);
--Add 1 million rows. 20 seconds.
begin
for i in 1 .. 10 loop
insert into orders_cluster
select rownum + i * 100000, mod(level, 100)+ i * 100000, level
from dual connect by level <= 100000;
commit;
end loop;
end;
/
create unique index orders_cluster_idx on orders_cluster(merchantid, transactionid);
begin
dbms_stats.gather_table_stats(user, 'ORDERS_CLUSTER');
end;
/
नियमित तालिका बनाएं (तुलना के लिए)
drop table orders_table;
create table orders_table
(
id number,
MerchantID number,
TransactionID varchar2(20)
) nologging;
--Add 1 million rows. 2 seconds.
begin
for i in 1 .. 10 loop
insert into orders_table
select rownum + i * 100000, mod(level, 100)+ i * 100000, level
from dual connect by level <= 100000;
commit;
end loop;
end;
/
create unique index orders_table_idx on orders_table(merchantid, transactionid);
begin
dbms_stats.gather_table_stats(user, 'ORDERS_TABLE');
end;
/
ट्रेस उदाहरण
एसक्यूएल*प्लस ऑटोट्रेस व्याख्या योजना खोजने और प्रति स्टेटमेंट I/O गतिविधि को ट्रैक करने का एक त्वरित तरीका है। I/O अनुरोधों की संख्या को "संगत हो जाता है" के रूप में लेबल किया गया है और यह किए गए कार्य की मात्रा को मापने का एक अच्छा तरीका है। यह कोड दर्शाता है कि अन्य वर्गों के लिए संख्याएँ कैसे उत्पन्न की गईं। चीजों को गर्म करने के लिए अक्सर प्रश्नों को एक से अधिक बार चलाने की आवश्यकता होती है।
SQL> set autotrace on;
SQL> select * from orders_cluster where merchantid = 100001 and transactionid = '2';
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 621801084
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 16 | 1 (0)| 00:00:01 |
|* 1 | TABLE ACCESS HASH| ORDERS_CLUSTER | 1 | 16 | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("MERCHANTID"=100001 AND "TRANSACTIONID"='2')
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
31 consistent gets
0 physical reads
0 redo size
485 bytes sent via SQL*Net to client
540 bytes received via SQL*Net from client
1 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
0 rows processed
SQL>
इष्टतम हैशकी, ट्रेड-ऑफ ढूंढें
इष्टतम पढ़ने के प्रदर्शन के लिए सभी हैश टकराव एक ब्लॉक में फिट होना चाहिए (सभी Oracle I/O प्रति ब्लॉक, आमतौर पर 8K) किए जाते हैं। सही भंडारण प्राप्त करना मुश्किल है और हैश एल्गोरिथ्म, भंडारण आकार (ब्लॉक आकार के समान नहीं), और हैश कुंजियों (बाल्टी) की संख्या जानने की आवश्यकता है। Oracle में एक डिफ़ॉल्ट एल्गोरिदम और आकार होता है इसलिए केवल एक विशेषता, हैश कुंजियों की संख्या पर ध्यान केंद्रित करना संभव है।
अधिक हैश कुंजियाँ कम टकराव की ओर ले जाती हैं। यह टेबल एक्सेस हैश प्रदर्शन के लिए अच्छा है क्योंकि पढ़ने के लिए केवल एक ब्लॉक है। नीचे विभिन्न हैशकी आकारों के लिए संगत की संख्या दी गई है। तुलना के लिए एक इंडेक्स एक्सेस भी शामिल है। पर्याप्त हैशकी के साथ ब्लॉक की संख्या इष्टतम संख्या तक घट जाती है, 1.
Method Consistent Gets (for transactionid = 1, 20, 300, 4000, and 50000)
Index 4, 3, 3, 3, 3
Hashkeys 100 1, 31, 31, 31, 31
Hashkeys 1000 1, 3, 4, 4, 4
Hashkeys 10000 1, 1, 1, 1, 1
अधिक हैश कुंजियाँ भी अधिक बकेट, अधिक व्यर्थ स्थान, और धीमी तालिका एक्सेस पूर्ण संचालन की ओर ले जाती हैं।
Table type Space in MB
HeapTable 24MB
Hashkeys 100 26MB
hashkeys 1000 30MB
hashkeys 10000 81MB
मेरे परिणामों को पुन:पेश करने के लिए, एक नमूना क्वेरी का उपयोग करें जैसे select * from orders_cluster where merchantid = 100001 and transactionid = '1';
और अंतिम मान को 1, 20, 300, 4000, और 50000 में बदलें।
प्रदर्शन तुलना
लगातार हो जाता है अनुमानित और मापने में आसान है, लेकिन दिन के अंत में केवल दीवार घड़ी का समय मायने रखता है। हैरानी की बात है कि इंडेक्स एक्सेस के साथ 4 गुना अधिक लगातार मिलता है, इष्टतम हैश क्लस्टर परिदृश्य की तुलना में अभी भी तेज है।
--3.5 seconds for b-tree access.
declare
v_count number;
begin
for i in 1 .. 100000 loop
select count(*)
into v_count
from orders_table
where merchantid = 100000 and transactionid = '1';
end loop;
end;
/
--3.8 seconds for hash cluster access.
declare
v_count number;
begin
for i in 1 .. 100000 loop
select count(*)
into v_count
from orders_cluster
where merchantid = 100000 and transactionid = '1';
end loop;
end;
/
मैंने चर विधेय के साथ परीक्षण की भी कोशिश की लेकिन परिणाम समान थे।
क्या यह स्केल करता है?
नहीं, हैश क्लस्टर स्केल नहीं करते हैं। TABLE ACCESS HASH की O(1) समय जटिलता और INDEX UNIQUE SCAN की O(log n) समय जटिलता के बावजूद, हैश क्लस्टर कभी भी बी-ट्री इंडेक्स से बेहतर प्रदर्शन नहीं करते हैं।
मैंने उपरोक्त नमूना कोड को 10 मिलियन पंक्तियों के साथ आजमाया। हैश क्लस्टर लोड करने के लिए दर्दनाक रूप से धीमा था, और अभी भी SELECT प्रदर्शन पर इंडेक्स का प्रदर्शन कम था। मैंने इसे 100 मिलियन पंक्तियों तक बढ़ाने की कोशिश की, लेकिन सम्मिलन में 11 दिन लगने वाले थे।
अच्छी खबर यह है कि बी * पेड़ अच्छी तरह से बढ़ते हैं। उपरोक्त उदाहरण में 100 मिलियन पंक्तियों को जोड़ने के लिए सूचकांक में केवल 3 स्तरों की आवश्यकता होती है। मैंने सभी DBA_INDEXES
को देखा एक बड़े डेटाबेस वातावरण (सैकड़ों डेटाबेस और डेटा की एक पेटाबाइट) के लिए - सबसे खराब सूचकांक में केवल 7 स्तर थे। और वह VARCHAR2(4000)
. पर एक पैथोलॉजिकल इंडेक्स था स्तंभ। ज्यादातर मामलों में आपके बी-ट्री इंडेक्स टेबल के आकार की परवाह किए बिना उथले रहेंगे।
इस मामले में, O(log n) O(1) को हरा देता है।
लेकिन क्यों?
खराब हैश क्लस्टर प्रदर्शन शायद चीजों को सरल बनाने और हैश क्लस्टर को अच्छी तरह से काम करने के लिए आवश्यक विवरणों को छिपाने के ओरेकल के प्रयास का शिकार है। क्लस्टर को सेटअप करना और ठीक से उपयोग करना मुश्किल है और वैसे भी शायद ही कभी कोई महत्वपूर्ण लाभ प्रदान करेगा। पिछले कुछ दशकों में Oracle ने उनमें बहुत अधिक प्रयास नहीं किया है।
टिप्पणीकार सही हैं कि एक साधारण बी-ट्री इंडेक्स सबसे अच्छा है। लेकिन यह स्पष्ट नहीं है कि यह सच क्यों होना चाहिए और डेटाबेस में उपयोग किए जाने वाले एल्गोरिदम के बारे में सोचना अच्छा है।