Schnelles Lesen von CSV-Dateien - 1 billion row challenge in SQL and Oracle Database - bei "Gerald on IT"

Über die Oracle Datenbanken Monthly News bin ich auf den sehr interessanten Beitrag


gestoßen. 
In Kurzform: Es geht um das (sehr) schnelle Auswerten einer Wetterdaten-CSV-Datei mit 1 Mrd Zeilen.

Spannend daran: Beispiele, wie das Einlesen/Abfragen von external Tables beschleunigt werden kann.

Die Grundform ist:
SELECT *
 FROM EXTERNAL
 (
   (
     station_name  VARCHAR2(26),
     measurement   NUMBER(3,1)
   )
   TYPE oracle_loader
   DEFAULT DIRECTORY brc
   ACCESS PARAMETERS
   (
     RECORDS DELIMITED BY NEWLINE
     FIELDS CSV WITHOUT EMBEDDED TERMINATED BY ';'
   )
   LOCATION ('measurements.txt')
   REJECT LIMIT UNLIMITED
 ) measurements
FETCH FIRST 10 ROWS ONLY;

Um alle Zeilen sehr schnell zu lesen, gibt es folgende Verbesserungen:


- Parallelisierung
explicitly defining the parallelization level with /*+ PARALLEL (x) */
Wichtig dabei
The important part here is the WITHOUT EMBEDDED 
weil aus WITH EMBEDDED folgt intra-datafile parallelism is disabled
schaut dann so aus:
SELECT /*+ PARALLEL (32) */ COUNT(*)
  FROM EXTERNAL
  (
    (
      station_name  VARCHAR2(26),
      measurement   NUMBER(3,1)
    )
    TYPE oracle_loader
    DEFAULT DIRECTORY brc
    ACCESS PARAMETERS
    (
      RECORDS DELIMITED BY NEWLINE
      FIELDS CSV WITHOUT EMBEDDED TERMINATED BY ';'
    )
    LOCATION ('measurements.txt')
    REJECT LIMIT UNLIMITED
  ) measurements;


- Wechsel des Treibers (oracle_bigdata statt oracle_loader)
Beispiel:
CREATE TABLE measurements_ext
(
  station_name  VARCHAR2(26),
  measurement   NUMBER(3,1)
)
ORGANIZATION EXTERNAL
(
  TYPE oracle_bigdata
  DEFAULT DIRECTORY brc
  ACCESS PARAMETERS
  (
    com.oracle.bigdata.fileformat=csv
    com.oracle.bigdata.csv.rowformat.separatorcharacter=';'
  )
  LOCATION ('measurements.txt')
)
REJECT LIMIT UNLIMITED;


- auch interessant: oracle_loader mit NODIRECTIO und expliziter Spaltendefinition statt FIELDS CSV
schaut dann so aus:
SELECT /*+ PARALLEL (32) */ COUNT(*)
  FROM EXTERNAL
  (
    (
      station_name  VARCHAR2(26),
      measurement   NUMBER(3,1)
    )
    TYPE oracle_loader
    DEFAULT DIRECTORY brc
    ACCESS PARAMETERS
    (
      RECORDS DELIMITED BY NEWLINE
      IO_OPTIONS (NODIRECTIO)
FIELDS TERMINATED BY ';'
      (
        station_name CHAR(26),
        measurement  CHAR(5)
      )
    )
    LOCATION ('measurements.txt')
    REJECT LIMIT UNLIMITED
  ) measurements;


Fazit: Interessante Möglichkeiten sehr schnell auf große externe Dateien zuzugreifen.


Kommentare

Beliebte Posts aus diesem Blog

PGA unter Oracle 11g

trunc(sysdate) - nette Spiele mit dem Datum

Datapump - Verzeichnis erstellen