সূচী কলাম ক্রম নির্বাচন করার সময়, ওভাররাইডিং উদ্বেগটি হ'ল:
আমার প্রশ্নের মধ্যে এই কলামের বিরুদ্ধে (সমতা) পূর্বাভাস আছে?
যদি কোনও কলামটি যেখানে কোনও ধারায় উপস্থিত না হয়, তবে এটি সূচকের (1) মূল্যবান নয়
ঠিক আছে, সুতরাং আপনি প্রতিটি কলামের বিরুদ্ধে একটি টেবিল এবং ক্যোয়ারী পেয়েছেন। কখনও কখনও একাধিক।
কীভাবে সূচকে সিদ্ধান্ত নেবেন?
একটি উদাহরণ তাকান। এখানে তিনটি কলাম সহ একটি টেবিল। একটিতে 10 টি মান রয়েছে, অন্যটি 1000, শেষ 10,000:
create table t(
few_vals varchar2(10),
many_vals varchar2(10),
lots_vals varchar2(10)
);
insert into t
with rws as (
select lpad(mod(rownum, 10), 10, '0'),
lpad(mod(rownum, 1000), 10, '0'),
lpad(rownum, 10, '0')
from dual connect by level <= 10000
)
select * from rws;
commit;
select count(distinct few_vals),
count(distinct many_vals) ,
count(distinct lots_vals)
from t;
COUNT(DISTINCTFEW_VALS) COUNT(DISTINCTMANY_VALS) COUNT(DISTINCTLOTS_VALS)
10 1,000 10,000
এগুলি শূন্যের সাথে প্যাডযুক্ত সংখ্যাগুলি numbers এটি পরে সংক্ষেপণের বিষয়ে বিন্দুটি তৈরি করতে সহায়তা করবে।
সুতরাং আপনি তিনটি সাধারণ জিজ্ঞাসা পেয়েছেন:
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where few_vals = '0000000001';
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where lots_vals = '0000000001';
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where lots_vals = '0000000001'
and few_vals = '0000000001';
আপনি কি সূচক করবেন?
পুরো টেবিল স্ক্যানের চেয়ে মাত্র কয়েকটি_ভালগুলিতে একটি সূচক কেবলমাত্র প্রান্তিকভাবে ভাল:
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where few_vals = '0000000001';
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST -PREDICATE'));
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 61 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 61 |
| 2 | VIEW | VW_DAG_0 | 1 | 1000 | 1000 |00:00:00.01 | 61 |
| 3 | HASH GROUP BY | | 1 | 1000 | 1000 |00:00:00.01 | 61 |
| 4 | TABLE ACCESS FULL| T | 1 | 1000 | 1000 |00:00:00.01 | 61 |
-------------------------------------------------------------------------------------------
select /*+ index (t (few_vals)) */
count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where few_vals = '0000000001';
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST -PREDICATE'));
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 58 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 58 |
| 2 | VIEW | VW_DAG_0 | 1 | 1000 | 1000 |00:00:00.01 | 58 |
| 3 | HASH GROUP BY | | 1 | 1000 | 1000 |00:00:00.01 | 58 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 1 | 1000 | 1000 |00:00:00.01 | 58 |
| 5 | INDEX RANGE SCAN | FEW | 1 | 1000 | 1000 |00:00:00.01 | 5 |
-------------------------------------------------------------------------------------------------------------
সুতরাং এটি নিজের অনুসারে মূল্যবান হওয়ার সম্ভাবনা কম। প্রচুর_ভালোগুলিতে প্রশ্নগুলি কয়েকটি সারি ফেরত দেয় (এই ক্ষেত্রে 1 জন)। সুতরাং এটি অবশ্যই নির্ধারণের মূল্যবান।
তবে উভয় কলামের বিরুদ্ধেই কি হবে?
আপনার কি সূচক করা উচিত:
( few_vals, lots_vals )
অথবা
( lots_vals, few_vals )
কৌতুক প্রশ্ন!
উত্তর না হয়।
অবশ্যই কয়েকটি_ভাল দীর্ঘ স্ট্রিং। সুতরাং আপনি এটি থেকে ভাল সংক্ষেপণ পেতে পারেন। এবং আপনি (সম্ভবত) লট_ভালগুলিতে ভবিষ্যদ্বাণীযুক্ত (কয়েকটি_ভাল, প্রচুর_ভাল) ব্যবহার করে প্রশ্নের জন্য একটি সূচক স্কিপ স্ক্যান পান। তবে আমি এখানে নেই, যদিও এটি সম্পূর্ণ স্ক্যানের চেয়ে উল্লেখযোগ্যভাবে আরও ভাল পারফর্ম করে:
create index few_lots on t(few_vals, lots_vals);
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where lots_vals = '0000000001';
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST -PREDICATE'));
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 61 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 61 |
| 2 | VIEW | VW_DAG_0 | 1 | 1 | 1 |00:00:00.01 | 61 |
| 3 | HASH GROUP BY | | 1 | 1 | 1 |00:00:00.01 | 61 |
| 4 | TABLE ACCESS FULL| T | 1 | 1 | 1 |00:00:00.01 | 61 |
-------------------------------------------------------------------------------------------
select /*+ index_ss (t few_lots) */count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where lots_vals = '0000000001';
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST -PREDICATE'));
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 13 | 11 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 13 | 11 |
| 2 | VIEW | VW_DAG_0 | 1 | 1 | 1 |00:00:00.01 | 13 | 11 |
| 3 | HASH GROUP BY | | 1 | 1 | 1 |00:00:00.01 | 13 | 11 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 1 | 1 | 1 |00:00:00.01 | 13 | 11 |
| 5 | INDEX SKIP SCAN | FEW_LOTS | 1 | 40 | 1 |00:00:00.01 | 12 | 11 |
----------------------------------------------------------------------------------------------------------------------
আপনি কি জুয়া খেলা পছন্দ করেন? (2)
সুতরাং আপনার এখনও অগ্রণী কলাম হিসাবে প্রচুর_ভালো সহ একটি সূচক প্রয়োজন। এবং কমপক্ষে এই ক্ষেত্রে যৌগিক সূচক (কয়েকটি, প্রচুর) ঠিক একই পরিমাণে কাজ করে (প্রচুর)
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where lots_vals = '0000000001'
and few_vals = '0000000001';
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST -PREDICATE'));
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 3 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 3 |
| 2 | VIEW | VW_DAG_0 | 1 | 1 | 1 |00:00:00.01 | 3 |
| 3 | HASH GROUP BY | | 1 | 1 | 1 |00:00:00.01 | 3 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 1 | 1 | 1 |00:00:00.01 | 3 |
| 5 | INDEX RANGE SCAN | FEW_LOTS | 1 | 1 | 1 |00:00:00.01 | 2 |
-------------------------------------------------------------------------------------------------------------
create index lots on t(lots_vals);
select /*+ index (t (lots_vals)) */count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where lots_vals = '0000000001'
and few_vals = '0000000001';
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST -PREDICATE'));
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 3 | 1 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 3 | 1 |
| 2 | VIEW | VW_DAG_0 | 1 | 1 | 1 |00:00:00.01 | 3 | 1 |
| 3 | HASH GROUP BY | | 1 | 1 | 1 |00:00:00.01 | 3 | 1 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 1 | 1 | 1 |00:00:00.01 | 3 | 1 |
| 5 | INDEX RANGE SCAN | LOTS | 1 | 1 | 1 |00:00:00.01 | 2 | 1 |
----------------------------------------------------------------------------------------------------------------------
এমন কেস থাকবে যেখানে যৌগিক সূচক আপনাকে 1-2 আইও সংরক্ষণ করে। তবে এই সাশ্রয়ের জন্য দুটি সূচকের মূল্য কী?
এবং সম্মিলিত সূচীতে আরও একটি সমস্যা আছে। LOTS_VALS সহ তিনটি সূচকের জন্য ক্লাস্টারিং ফ্যাক্টরের তুলনা করুন:
create index lots on t(lots_vals);
create index lots_few on t(lots_vals, few_vals);
create index few_lots on t(few_vals, lots_vals);
select index_name, leaf_blocks, distinct_keys, clustering_factor
from user_indexes
where table_name = 'T';
INDEX_NAME LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR
FEW_LOTS 47 10,000 530
LOTS_FEW 47 10,000 53
LOTS 31 10,000 53
FEW 31 10 530
লক্ষ্য করুন যে কয়েকটি_লটসের জন্য ক্লাস্টারিং ফ্যাক্টরটি 10x বেশি লট এবং লট_ফিউয়ের চেয়ে ! এবং এটি শুরু করার জন্য নিখুঁত ক্লাস্টারিং সহ একটি ডেমো টেবিলের মধ্যে রয়েছে। বাস্তব বিশ্বের ডাটাবেসে এর প্রভাব আরও খারাপ হতে পারে।
তাহলে এতো খারাপ কী?
ক্লাস্টারিং ফ্যাক্টর হ'ল সূচকটি কতটা "আকর্ষণীয়" তা নির্ধারণ করার অন্যতম মূল চালক। এটি যত বেশি, অপটিমাইজারটি এটি চয়ন করার সম্ভাবনা কম। বিশেষত যদি প্রচুর_ভালগুলি প্রকৃতপক্ষে অনন্য না হয় তবে তবুও সাধারণত মূল্য প্রতি কয়েকটি সারি থাকে। আপনি যদি দুর্ভাগ্য হন তবে এটি অপটিমাইজারকে মনে করতে পারে যে একটি সম্পূর্ণ স্ক্যান সস্তা is
ঠিক আছে, সুতরাং কয়েকটি_ভাল এবং প্রচুর_ভাল সহ যৌগিক সূচকগুলিতে কেবল প্রান্তের ক্ষেত্রে সুবিধা রয়েছে।
কয়েকটি_ভাল এবং বহু_ওয়ালগুলিকে ফিল্টারিং করা প্রশ্নাগুলি সম্পর্কে কী?
একক কলাম সূচকগুলি কেবলমাত্র ছোট সুবিধা দেয়। তবে সম্মিলিত তারা কয়েকটি মান ফেরত দেয়। সুতরাং একটি যৌগিক সূচক একটি ভাল ধারণা। তবে কোন পথে?
আপনি যদি প্রথম কয়েকটি স্থাপন করেন তবে শীর্ষস্থানীয় কলামটি সংকোচন করা আরও ছোট করে তুলবে
create index few_many on t(many_vals, few_vals);
create index many_few on t(few_vals, many_vals);
select index_name, leaf_blocks, distinct_keys, clustering_factor
from user_indexes
where index_name in ('FEW_MANY', 'MANY_FEW');
INDEX_NAME LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR
FEW_MANY 47 1,000 10,000
MANY_FEW 47 1,000 10,000
alter index few_many rebuild compress 1;
alter index many_few rebuild compress 1;
select index_name, leaf_blocks, distinct_keys, clustering_factor
from user_indexes
where index_name in ('FEW_MANY', 'MANY_FEW');
INDEX_NAME LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR
MANY_FEW 31 1,000 10,000
FEW_MANY 34 1,000 10,000
নেতৃস্থানীয় কলামে কম ভিন্ন ভিন্ন মান সহ আরও ভাল সংক্ষেপে। সুতরাং এই সূচকটি পড়ার সামান্য কাজ রয়েছে। তবে কেবল সামান্য। এবং উভয়ই ইতিমধ্যে মূল (25% আকার হ্রাস) এর চেয়ে ছোট একটি ছোট অংশ।
এবং আপনি আরও যেতে পারেন এবং পুরো সূচকটি সংকুচিত করতে পারেন!
alter index few_many rebuild compress 2;
alter index many_few rebuild compress 2;
select index_name, leaf_blocks, distinct_keys, clustering_factor
from user_indexes
where index_name in ('FEW_MANY', 'MANY_FEW');
INDEX_NAME LEAF_BLOCKS DISTINCT_KEYS CLUSTERING_FACTOR
FEW_MANY 20 1,000 10,000
MANY_FEW 20 1,000 10,000
এখন উভয় সূচক একই আকারে ফিরে এসেছে। নোট করুন এটি কয়েকটি এবং অনেকের মধ্যে একটি সম্পর্কের সত্যিকারের সুবিধা গ্রহণ করে। আবার এটি অসম্ভব যে আপনি আসল বিশ্বে এই ধরণের সুবিধা দেখতে পাবেন।
এখনও পর্যন্ত আমরা কেবল সমতা পরীক্ষার বিষয়ে কথা বলেছি। প্রায়শই সম্মিলিত সূচীগুলির সাথে আপনার কোনও একটি কলামের মধ্যে বৈষম্য থাকবে। উদাহরণস্বরূপ "গত N দিনগুলিতে কোনও গ্রাহকের জন্য অর্ডার / শিপমেন্ট / চালানগুলি পান" এর মতো প্রশ্নগুলি।
আপনার যদি এই ধরণের প্রশ্ন থাকে তবে আপনি সূচকের প্রথম কলামের বিপরীতে সমতা চান:
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where few_vals < '0000000002'
and many_vals = '0000000001';
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST -PREDICATE'));
-------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 12 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 12 |
| 2 | VIEW | VW_DAG_0 | 1 | 10 | 10 |00:00:00.01 | 12 |
| 3 | HASH GROUP BY | | 1 | 10 | 10 |00:00:00.01 | 12 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 1 | 10 | 10 |00:00:00.01 | 12 |
| 5 | INDEX RANGE SCAN | FEW_MANY | 1 | 10 | 10 |00:00:00.01 | 2 |
-------------------------------------------------------------------------------------------------------------
select count (distinct few_vals || ':' || many_vals || ':' || lots_vals )
from t
where few_vals = '0000000001'
and many_vals < '0000000002';
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST -PREDICATE'));
----------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | Reads |
----------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 12 | 1 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 12 | 1 |
| 2 | VIEW | VW_DAG_0 | 1 | 2 | 10 |00:00:00.01 | 12 | 1 |
| 3 | HASH GROUP BY | | 1 | 2 | 10 |00:00:00.01 | 12 | 1 |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| T | 1 | 2 | 10 |00:00:00.01 | 12 | 1 |
| 5 | INDEX RANGE SCAN | MANY_FEW | 1 | 1 | 10 |00:00:00.01 | 2 | 1 |
----------------------------------------------------------------------------------------------------------------------
লক্ষ্য করুন তারা বিপরীত সূচকটি ব্যবহার করছে।
টি এল; ডিআর
- সমতা শর্তযুক্ত কলামগুলি সূচকে প্রথম হওয়া উচিত।
- যদি আপনার ক্যোয়ারিতে সাম্যগুলির সাথে একাধিক কলাম রয়েছে তবে প্রথমে কয়েকটিকে আলাদা আলাদা মান দিয়ে রাখলে সেরা সংকোচনের সুবিধা হবে
- ইনডেক্স স্কিপ স্ক্যানগুলি সম্ভব হলেও আপনার আত্মবিশ্বাস থাকা দরকার এটি ভবিষ্যতের জন্য একটি কার্যকর বিকল্প হিসাবে থাকবে
- নিকট-অনন্য কলাম সহ সংমিশ্র সূচকগুলি ন্যূনতম সুবিধা দেয়। আপনার অবশ্যই 1-2 আইওএস সংরক্ষণ করতে হবে তা নিশ্চিত হন
1: কিছু ক্ষেত্রে এটি সূচীতে একটি কলাম অন্তর্ভুক্ত করা উচিত যদি এর অর্থ আপনার ক্যোয়ারীর সমস্ত কলামগুলি সূচীতে থাকে। এটি কেবলমাত্র একটি সূচি স্ক্যান সক্ষম করে, তাই আপনাকে টেবিলটি অ্যাক্সেস করার দরকার নেই।
2: যদি আপনি ডায়াগনস্টিকস এবং টিউনিংয়ের জন্য লাইসেন্স পেয়ে থাকেন তবে আপনি এসকিউএল প্ল্যান ম্যানেজমেন্টের সাহায্যে পরিকল্পনাটি স্কিপ স্কিনে বাধ্য করতে পারেন
ADDEDNDA
পিএস - আপনি যে দস্তাবেজগুলি উদ্ধৃত করেছেন তা 9 আই থেকে রয়েছে। এটাই পুনরায় পুরানো। আমি আরও সাম্প্রতিক কিছু সঙ্গে থাকি