Butuh saran tentang cara terbaik untuk memfilter file teks berdasarkan tabel referensi

Saat ini saya sedang mencari cara untuk mengoptimalkan proses yang
memerlukan waktu lama untuk dijalankan.

  • Ada sekitar 270 file teks yang akan disaring.
  • Setiap file memiliki sekitar 70k~150k baris.
  • Tabel referensi biasanya memiliki sekitar 16m catatan di bawah Oracle 10g.
  • Prosesnya dijalankan setiap jam.
  • Ada kemungkinan bahwa 9 contoh proses tersebut dapat dijalankan hampir
    secara bersamaan.

Apa yang saat ini saya lakukan adalah memasukkan tabel referensi ke dalam sebuah file, menyalinnya ke dalam
hash, melakukan hal yang sama dengan file teks, lalu melakukan pencocokan kunci hash.
Catatan apa pun pada file teks yang ditemukan di daftar referensi akan dibuang.

Hal ini diulangi untuk seluruh 270 file, namun bagian spooling hanya dilakukan
sekali di awal.

Namun pendekatan ini menghabiskan sekitar 300mb~500mb RAM, dan dengan
kemungkinan menjalankan beberapa proses tersebut hampir pada
waktu yang sama, ini merupakan mimpi buruk bagi server kami.

Adakah ide bagaimana melakukan ini dengan lebih baik?


person cr8ivecodesmith    schedule 24.02.2012    source sumber


Jawaban (2)


Saya menyarankan Anda untuk hanya memuat data DB ke memori, dan memproses file seperti (maaf, itu kodesemu, tetapi Anda harus mendapatkan ide dan menerapkannya di Perl):

HashSet dbData = GetDataFromDB();
foreach(filename in filenames) {
    FileHandle handle = OpenRead(filename);
    FileHandle tmphandle = OpenWrite(filename + ".tmp");
    while(string line = handle.ReadLine()) {
        if(!dbData.Contains(line)) {
            tmphandle.Write(line);
        }
    }
    tmphandle.Flush();
    tmphandle.Close();
    handle.Close();
    Delete(filename);
    Rename(tmpfilename, filename);
}

Ini hanya akan memakan RAM sebanyak yang dibutuhkan tabel referensi Anda.

person penartur    schedule 24.02.2012

Ini sepertinya sesuatu yang dapat dilakukan secara efisien dalam database (anti-gabungan besar).

Anda dapat menggunakan UTL_FILE untuk membaca file dan bandingkan langsung dengan tabel referensi Anda. Anda bisa menggunakan fungsi wrapper untuk memilih langsung file Anda:

CREATE OR REPLACE TYPE tab_varchar AS TABLE OF VARCHAR2(4000);
/

CREATE OR REPLACE FUNCTION select_file(p_dir VARCHAR2, p_file VARCHAR2)
   RETURN tab_varchar
   PIPELINED IS
   l_file utl_file.file_type := utl_file.fopen(p_dir, p_file, 'r', 4000);
   l_line VARCHAR2(4000);
BEGIN
   LOOP
      BEGIN
         utl_file.get_line(l_file, l_line);
      EXCEPTION
         WHEN No_Data_Found THEN
            EXIT;
      END;
      PIPE ROW (l_line);
   END LOOP;
   utl_file.fclose(l_file);
   RETURN;
END;
/

Ini akan memungkinkan Anda untuk memilih langsung data Anda, misalnya ini akan mengembalikan konten file C:\tmp\a.txt

create directory tmp_dir as 'C:\tmp\';

select column_value from table(select_file('TMP_DIR', 'a.txt'));

Dari sini, satu kueri akan baik-baik saja untuk setiap file, seperti:

INSERT INTO ref_table r
   (SELECT column_value
      FROM table(select_file(:dir, :file_name)
     WHERE column_value NOT IN (SELECT ref_value
                                  FROM ref_table
                                 WHERE ref_value IS NOT NULL)
       AND column_value IS NOT NULL);
person Vincent Malgrat    schedule 24.02.2012