0

UPDATE:

Right now I am trying to take in to an array around 120M of rows. Reason I'm not doing this over UTL_file is because in our production server it requires oracle user access to write and move the written flat-file into our desired directory. Add in to the problem is that there are still a lot of text manipulations needed after extraction which I think is a job for Perl.

What I want to do right now is to write my own implementation of the DBI::Iterator and all other dependencies it may need; to be clear though, not necessarily all. (like some methods only of DBI, then just idb_rows... just to get this running since I cannot install modules)

Original Question:

Good day, I'm relatively new to perl programming, A week ago I started receiving out of memory messages again in perl. I was able to get around this before by switching to 64 bit perl.

I just found yesterday that the kernel of my production machine is not allowing me to use more than 4GB of memory (in my other production server I am able to load large amounts of data to memory)

Here are my specific restrictions in my production server

  1. I am not allowed to install new modules of perl
  2. I am allowed, in a way, to install them locally but I am having trouble

What I intend to do now is to recreate this module. Iterator::DBI

I have no background of iterators. for the longest time I develop database extractions and ETL processes through the function below. It's my 1st time to encounter an out of memory error again after a year and a half of using the function below.

sub myDBI
{
    my ($filename) = @_; 
    my $query = "";
    unless(open(FILE,$filename))
    {
        Logger("[ ERR ] unable to open $SETTINGS{SQL_TRIGGER}\n");
        print
        die;
    }
    my @result=`sqlplus -S $SETTINGS{USER_NAME}/$SETTINGS{PASSWORD}\@$SETTINGS{DB_NAME} <<END
    SET HEADING OFF
    SET FEEDBACK OFF
    SET SERVEROUTPUT ON
    SET LINES 5000
    SET COLSEP "||"
    $query
    /
    `
    ;
    @result;
}
j0k
  • 22,600
  • 28
  • 79
  • 90
  • You seem to have failed to actually ask a question. What behavior are you seeing? What behavior do you expect to see? Open-ended design questions aren't what stack overflow is for. – xaxxon May 07 '13 at 02:55
  • Hi thank you for the advise, I updated my question. I expect to be able to implement my own version of idb_rows which is a function in DBI::Iterator, simply because I am not allowed to install modules in my production server. The code I posted above is not working in my new server because I am running out of memory. This will be my very 1st time to deal with perl iterators. Thanks again in advance. – user2309407 May 07 '13 at 03:05

1 Answers1

1

You have several options:

  • If you have local::lib installed, you can install CPAN modules like Iterator::DBI to a user directory. You'll just need to set some environment variables to specify which directory to use.

    export PERL_MB_OPT='--install_base /home/username/perl5'
    export PERL_MM_OPT='INSTALL_BASE=/home/username/perl5'
    export PERL5LIB='/home/username/perl5/lib/perl5/i386-linux:/home/username/perl5/lib/perl5'
    export PATH="/home/username/perl5/bin:$PATH"
    
  • You actually don't need Iterator::DBI. That module just wraps an Iterator object around a DBI statement handle, which is an iterator itself. So you can just use DBI directly to connect to the database. (Note that either way, you'll connect to the database directly rather than going through sqlplus.)

    use DBI;
    my $dbh = DBI->connect(...);
    my $sth = $dbh->prepare($sql_query);
    $sth->execute(@params);
    # iterate
    while (my $row = $sth->fetchrow_arrayref) {
        ...
    }
    
  • If you really want to use Iterator::DBI and you can't install the module, you can just copy the source code directly and put it in ./Iterator/DBI.pm relative to your application. But the problem with this is you'll need to get around the dependencies. To do that I would replace exceptions with a simple die or croak, and replace Iterator with a closure (see chapter 5 of Higher Order Perl for how to do this). This option looks quite difficult for a beginner Perl programmer.

  • If you really can't get DBI working, you can pipe the sqlplus output to a file and iterate through the file.

stevenl
  • 6,736
  • 26
  • 33
  • Thanks will try this ASAP and get back to you again. I also see that Iterator::DBI also needs a few modules from DBI especially the database handler. can I also save the source as another pm file? – user2309407 May 07 '13 at 03:47
  • DBI is a core module that should be included with your perl installation. – stevenl May 07 '13 at 03:50
  • Well I get some errors when I run the test (ch04/listdsns: Enumerates all data sources and all installed drivers #) in the link below [link](http://oreilly.com/catalog/perldbi/chapter/ch04.html) `BEGIN failed--compilation aborted at /opt/perl_64/lib/site_perl/5.8.8/IA64.ARCHREV_0-thread-multi-LP64/DBD/Proxy.pm line 29. Compilation failed in require at (eval 15) line 3. Perhaps a module that DBD::Proxy requires hasn't been fully installed at ./ulimit.pl line 16` – user2309407 May 07 '13 at 06:04
  • You won't likely be using that module so you should be able to skip that test. Just make sure the test works for the DBD::Oracle driver. – stevenl May 07 '13 at 06:25
  • I like that idea of just copying the *.pm share how it is gonna look like in my code? How will I use it? – user2309407 May 07 '13 at 06:26
  • I actually don't recommend that because it is the most difficult of all the options unless you understand the module code and how to do iterators in Perl. My recommendation is to do option 2 which is less work. – stevenl May 07 '13 at 06:28