2016-09-30 1 views
0

Ich habe Szenario, wo ich suchen muss & Anzeige Datensätze aus riesigen Tabellen mit vielen Zeilen. Ich habe vordefinierte Suchkriterien für meine Tabellen, für die Benutzer den Filter bereitstellen können & klicken Sie auf Suche.Verwendung von Primärschlüssel in Oracle während der Suche erzwingen

eine Beispieltabelle Betrachtet:

CREATE TABLE suppliers 
(supplier_name varchar2(50) NOT NULL, 
    address varchar2(50), 
    city varchar2(50) NOT NULL, 
    state varchar2(25), 
    zip_code varchar2(10), 
    CONSTRAINT "suppliers_pk" PRIMARY KEY (supplier_name, city) 
); 


INSERT INTO suppliers VALUES ('ABCD','XXXX','YYYY','ZZZZ','95012'); 
INSERT INTO suppliers VALUES ('EFGH','MMMM','NNNN','OOOO','95010'); 
INSERT INTO suppliers VALUES ('IJKL','EEEE','FFFF','GGGG','95009'); 

Ich habe den Benutzer mit Suchfeldern als Primärschlüssel zur Verfügung gestellt - SUPPLIER_NAME, Stadt

Wenn er betritt die beiden Felder, meine Abfrageleistung seit gut es geht für Index-Scan

SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' and city = 'ZZZZ'; 

| Id | Operation     | Name   | Rows | Bytes | Cost (%CPU)| Time  | 
-------------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT   |    |  1 | 102 |  1 (0)| 00:00:01 | 
| 1 | TABLE ACCESS BY INDEX ROWID| SUPPLIERS |  1 | 102 |  1 (0)| 00:00:01 | 
|* 2 | INDEX UNIQUE SCAN   | suppliers_pk |  1 |  |  1 (0)| 00:00:01 | 

wenn er jedoch nur eine Suchfeld eingibt, wird meine Abfrageleistung schlecht gehen, da es für die vollständige Tabelle geht scannen

SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' ; 

| Id | Operation   | Name  | Rows | Bytes | Cost (%CPU)| Time  | 
------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT |   |  1 | 102 |  3 (0)| 00:00:01 | 
|* 1 | TABLE ACCESS FULL| SUPPLIERS |  1 | 102 |  3 (0)| 00:00:01 | 

Gibt es eine Möglichkeit Orakel zu zwingen, zu denken, dass es ein Primärschlüssel suchen ist, wenn ich nicht alle Schlüsselfelder auf der Suche haben, unter so etwas wie (was natürlich nicht funktioniert)

SELECT supplier_name, address, city, state, zip_code FROM suppliers where supplier_name = 'ABCD' and city = city; 

Danke.

+2

Oracle einen Skip-Scan-Index-Suche, wenn es das ist angemessen und effizienter als eine denkt vollständiger Tabellenscan Im Allgemeinen ist der Optimierer ziemlich gut darin, den besten Plan mit den verfügbaren Indizes auszuwählen, vorausgesetzt, die Statistiken sind aktuell. Wenn es denkt, dass es keinen Skip-Scan machen kann, brauchen Sie vielleicht einen separaten Index zu "city"? Es ist wahrscheinlich nicht effizient, sie für die Verwendung des PK-Index zu verwenden - sie wird wahrscheinlich einen vollständigen Index-Scan durchführen und dann immer noch die Datenblöcke für die relevanten Zeilen abrufen müssen. –

+3

Sie haben nur 3 Zeilen in Ihrer Tabelle. Fügen Sie 10 000 Zeilen hinzu, sammeln Sie Statistiken und analysieren Sie die Ergebnisse. –

+0

Danke, ich habe einen Tisch mit Millionen von Zeilen probiert, es hat einen INDEX RANGE SCAN statt FTS gemacht. – ppatkar

Antwort

0

Sie denken falsch darüber nach.

Der Abfrageoptimierer wählt basierend auf den zum Zeitpunkt des Analysierens der Abfrage verfügbaren Informationen (oder manchmal, wenn sich die Parameter geändert haben) den für die Abfrage besten Ausführungsplan aus. Im Allgemeinen - wenn Sie es die richtigen Informationen in Bezug auf Statistiken usw. geben, wird es in der Regel einen guten Job machen.

Sie könnten denken, dass Sie es besser wissen als es, aber denken Sie daran, dass Sie dies nicht für die Lebensdauer der Datenbank überwachen werden. Die Daten ändern sich, Sie möchten, dass die Datenbank reagieren und den Ausführungsplan bei Bedarf ändern kann.

Das heißt, wenn Sie festgelegt auf zwingen, den Index zu verwenden, können Sie einen Hinweis verwenden:

SELECT /*+ INDEX(suppliers suppliers_pk) */ 
supplier_name, address, city, state, zip_code FROM suppliers where 
supplier_name = 'ABCD' ; 
0

Eine vollständige Tabelle Scan ist nicht unbedingt schlecht. Sie haben nur wenige Zeilen in Ihrer Tabelle, daher hält der Optimierer es für besser, einen FTS als einen Indexbereichs-Scan durchzuführen. Es wird anfangen, den PK-Index zu verwenden, sobald das RDBMS es für besser hält, d. H. Sie haben viele Zeilen und die Beschränkung auf einen bestimmten Lieferanten reduziert das Ergebnis signifikant. Wenn Sie nur nach Stadt anstatt nach Lieferant suchen möchten, brauchen Sie einen anderen Index nur mit Stadt (oder zumindest mit Stadt beginnend). Beachten Sie, dass Sie die Tabellenstatistik möglicherweise aktualisieren müssen, nachdem Sie Ihre Tabelle mit Massendaten geladen haben. Es ist immer wichtig, die Abfrageleistung mit irgendwie realistischen Datenmengen zu testen.

0

Der Index wird zuerst auf supplier_name Sekunde in der Stadt organisiert, daher ist es nicht möglich, diesen Index nur für Abfragen basierend auf der Stadt zu verwenden. Bitte erstellen Sie einen zweiten Index nur basierend auf Stadt. Dies wird Ihrer Anfrage helfen.

+0

[Das stimmt nicht unbedingt] (https://docs.oracle.com/cd/E11882_01/server.112/e40540/indexiot.htm#CHDHGIHA). Obwohl in diesem Fall der Optimierer denkt, dass ein Skip-Scan nicht effizient ist, vermutlich weil es viele Lieferanten gibt, so dass er nicht selektiv genug für diesen Ansatz ist. –

Verwandte Themen