2009-08-16 6 views
1

Ich verwende Oracle 10g Enterprise Edition.Wie sollte ich in Oracle eine Partition mit einer varchar2-Spalte partitionieren? Ist das eine schlechte Idee?

Eine Tabelle in unserer Oracle-Datenbank speichert die Soundex-Wertdarstellung einer anderen Textspalte. Wir verwenden eine angepasste Soundex-Implementierung, bei der die Soundex-Werte länger sind als die von herkömmlichen Soundex-Algorithmen (wie die von Oracle verwendeten). Das ist wirklich nebensächlich.

Grundsätzlich habe ich eine varchar2 Spalte, die Werte mit einem einzelnen Zeichen gefolgt von einer dynamischen Anzahl von numerischen Werten (z. B. 'A12345', 'S382771', etc) enthält. Die Tabelle ist durch eine andere Spalte partitioniert, aber ich möchte der soundex-Spalte einen partitionierten Index hinzufügen, da dieser häufig durchsucht wird. Beim Versuch, eine bereichspartitionierte Index mit dem ersten Zeichen der soundex Spalte hinzuzufügen funktionierte es toll:

create index IDX_NAMES_SOUNDEX on NAMES_SOUNDEX (soundex) 
global partition by range (soundex) (
    partition IDX_NAMES_SOUNDEX_PART_A values less than ('B'), -- 'A%' 
    partition IDX_NAMES_SOUNDEX_PART_B values less than ('C'), -- 'B%' 
    ... 
); 

jedoch in I, um gleichmäßiger die Größe der Partitionen zu verteilen, wurde ich von der einige Partitionen definieren möchten ersten beiden Zeichen, etwa so:

create index IDX_NAMES_SOUNDEX on NAMES_SOUNDEX (soundex) 
global partition by range (soundex) (
    partition IDX_NAMES_SOUNDEX_PART_A5 values less than ('A5'), -- 'A0% - A4%' 
    partition IDX_NAMES_SOUNDEX_PART_A values less than ('B'), -- 'A4% - A9%' 
    partition IDX_NAMES_SOUNDEX_PART_B values less than ('C'), -- 'B%' 
    ... 
); 

ich bin nicht sicher, wie man richtig Partition mit varchar2 Spalten reichen. Ich bin sicher, dass dies eine weniger als ideale Wahl ist, vielleicht kann jemand eine bessere Lösung empfehlen. Hier ist eine Verteilung der soundex Daten in meinem Tisch:

----------------------------------- 
| SUBSTR(SOUNDEX,1,1) | COUNT | 
----------------------------------- 
|     A | 6476349 | 
|     B | 854880 | 
|     D | 520676 | 
|     F | 1200045 | 
|     G | 280647 | 
|     H | 3048637 | 
|     J | 711031 | 
|     K | 1336522 | 
|     L | 348743 | 
|     M | 3259464 | 
|     N | 1510070 | 
|     Q | 276769 | 
|     R | 1263008 | 
|     S | 3396223 | 
|     V | 533844 | 
|     W | 555007 | 
|     Y | 348504 | 
|     Z | 1079179 | 
----------------------------------- 

Wie Sie sehen können, ist die Verteilung nicht gleichmäßig verteilt, weshalb ich Bereich Partitionen mit den ersten beiden Zeichen, anstatt nur das erste Zeichen definieren möchten .

Vorschläge?

Danke!

Antwort

3

Was genau ist Ihre Frage?

Wissen Sie nicht, wie Sie Ihre Tabelle in n gleiche Teile teilen können, um Skew zu vermeiden?

Das können Sie mit der Analysefunktion percentile_disc() tun.

Hier ein SQL PLUS-Beispiel mit n = 100, ich gebe zu, dass es nicht sehr anspruchsvoll ist, aber es wird die Arbeit machen.

set pages 0 
set lines 200 

drop table random_strings; 

create table random_strings 
as 
select upper(dbms_random.string('A', 12)) rndmstr 
from dual 
connect by level < 1000; 


spool parts 

select 'select '||level||'/100,percentile_disc('||level|| 
     '/100) within group (order by RNDMSTR) from random_strings;' 
     sql_statement 
from dual 
connect by level <= 100 
/

spool off 

Dies wird Ausgabe in Datei parts.lst:

select 1/100,percentile_disc(1/100) within group (order by RNDMSTR) from random_strings;                             
select 2/100,percentile_disc(2/100) within group (order by RNDMSTR) from random_strings;                             
select 3/100,percentile_disc(3/100) within group (order by RNDMSTR) from random_strings;             
... 
select 100/100,percentile_disc(100/100) within group (order by RNDMSTR) from random_strings;             

Jetzt können Sie Skript parts.lst ausführen, um die Partitionswerte zu erhalten. Jede Partition enthält zunächst 1% der Daten.

Script parts.lst AUSGABE:

,01 AJUDRRSPGMNP 
    ,02 AOMJZQPZASQZ 
    ,03 AWDQXVGLLUSJ 
    ,04 BIEPUHAEMELR 
    .... 
    ,99 ZTMHDWTXUJAR 
    1 ZYVJLNATVLOY 
+0

+1 Ich bin sicherlich ein Oracle-Anfänger. Ich wusste nichts über percentile_disc ... vielen, vielen Dank für den Tipp, es hat mir Kopfschmerzen und Frustration erspart, die versuchen, die Datenverteilung herauszufinden. Um die erste Zeile Ihrer Antwort zu beantworten, denke ich, was ich frage ist: Ist mein Ansatz zum Indexieren der Tabelle, die ich beschrieben, geeignet? –

+0

Sie fragen Bereiche ab, so dass Hash Partioing nicht hilft, weil nach dem Hashing die Nähe verloren geht. Ihr Ansatz zur Partitionierung ist also angemessen. Sie können PARTITION ... WERTE WENIGER ALS (MAXWERT)) für die letzte Partition verwenden, um Werte wie 'ZZZYY233' zu speichern. – tuinstoel

0

Wird die Tabelle zusätzlich zum SOUNDEX-Wert vom Partitionierungsschlüssel durchsucht? Oder wird gerade nach der SOUNDEX-Spalte gesucht?

Wenn Sie nur versuchen, eine gleichmäßige Verteilung von Daten zwischen Partitionen zu erreichen, haben Sie in Erwägung gezogen, Hash-Partitionen anstelle von Bereichspartitionen zu verwenden? Angenommen, Sie wählen eine Potenz von 2 für die Anzahl der Partitionen, dann sollten Sie eine ziemlich gleichmäßige Verteilung der Daten zwischen den Partitionen erreichen.

+0

Die Tabelle wird nach mehreren verschiedenen Spalten durchsucht, aber die Spalte, in der die Tabelle partitioniert ist, wird am häufigsten gesucht und bietet die natürlichste Methode zum Aufteilen der Daten. Allerdings müssen meine Benutzer noch in der Soundex-Spalte suchen können, weshalb ich versuche, einen guten partitionierten Index zu erstellen. Ich wollte eine Hash-Partition versuchen, aber ich lese auf Ask Tom, dass die Hash-Werte "ziemlich einzigartig" sein müssen. Im Falle meiner Tabelle beträgt die Anzahl der verschiedenen Soundex-Werte etwa 25% der Gesamtzahl der Zeilen (was viele nicht eindeutige Werte bedeutet). –

+0

Ich bin kein großer Partitionierungsexperte - aber wenn es nur etwa 4 Zeilen für jeden soundex-Wert gibt, würde ich das als "ziemlich eindeutig" bezeichnen - Hash-Partitionierung kann ein guter Weg sein, besonders wenn die Abfragen normalerweise auf einem bestimmten stehen Soundex-Wert (zB WHERE sndx = 'A12345'). Wenn Abfragen Bereiche betreffen (z. B. WHERE sndx LIKE 'A1234%'), wäre die Bereichspartitionierung wahrscheinlich besser. –

+0

Ja, Abfragen sind normalerweise in Bereichen. Ich habe versucht, eine Hash-Partition zu erstellen, aber einige Abfragen von Werten mit einer großen Anzahl von entsprechenden Zeilen erfordern immer noch vollständige Tabellen-Scans. Ich denke, Bereichsaufteilung ist definitiv die richtige Wahl. –

0

Sprich mit mir! Können Sie mir sagen, was Ihr Grund für die Partitionierung dieser Tabelle ist? Es klingt wie eine OLTP-Tabelle und muss nicht unbedingt partitioniert werden. Wir wollen nicht partitionieren, nur um zu sagen, dass wir partitioniert sind. Sagen Sie mir, was Sie durch Partitionierung dieser Tabelle erreichen wollen, und ich kann Ihnen bei der Auswahl eines korrekten Partitionierungsschemas helfen. Partitionierung ist nicht gleich schneller Abfragen. Es kann tatsächlich dazu führen, dass Ihre Abfragen in einigen Fällen langsamer sind.

Ich sehe einige Ihrer zusätzlichen Gedanken oben und ich glaube nicht, dass Sie Ihren Tisch partitionieren müssen. Wenn Ihre Abfragen Aggregate für ganze Partitionen erstellen, möchten Sie möglicherweise partitionieren. Wenn Sie Hunderte von Millionen von Datenzeilen haben möchten, können Sie sie partitionieren, um bei der DBA-Wartung zu helfen. Wenn Sie möchten, dass Ihre Abfragen schnell ausgeführt werden, reicht der Primärschlüssel-Index aus. Bitte lassen Sie mich wissen

Erstellen Sie einfach einen globalen Index auf Ihre gewünschten Spalten.

+0

Die Tabelle ist durch eine andere Spalte unterteilt. Es hat fast 100 Millionen Zeilen, also haben wir es für Wartbarkeit partitioniert. Die Tabelle wird mit einer Vielzahl von Spalten abgefragt. Eine Spalte, die stark abgefragt wird, ist die Spalte, die ich hier behandle, und um die Abfrageleistung zu verbessern, haben wir versucht, den Index dieser Spalte zu partitionieren. Der Gedanke ist, dass, wenn der Index - mit ~ 100M Einträgen - partitioniert ist, unsere Abfragen (die nach Bereich sind) schneller sein werden b/c Oracle muss nur eine bekannte Teilmenge der Werte im Index durchsuchen. –

Verwandte Themen