Re: Changing foreach loop for a while loop
by jZed (Prior) on Dec 30, 2004 at 01:44 UTC
|
You don't need a loop at all. Just use the SQL, Luke!
my $p_str = join ',', ('?') x @array;
my $sql = "
SELECT C58XX.CCLMyy, C58XX.CLINyy
FROM C58XX
WHERE C58XX.CCLMyy IN ( $p_str )
AND C58XX.CLINyy = $X_LINE
";
my $sth = $dbh->prepare( $sql );
$sth->execute( @array );
| [reply] [d/l] |
|
|
Hi, I think that your idea is good, different, can you walk me trough the code, just explaining what you had done.
Thank you!
| [reply] |
|
|
Well, the biggest thing is to realize that the SQL predicate IN allows you to search for multiple values in a single trip to the database. Rather than looping through values in perl and making a trip to the database for each one, you just make one trip and ask about all the values at once. There are some things that can be done quicker in perl and some things that can be done quicker in a database and this is an example of a case where, no matter how much you optimize your perl, your main loss of time is going to be in trips to the database so you want to think about shifting the load away from perl and toward SQL.
The only other tricky thing I have done is to dynamically generate a string of placeholders. If you do a super-search here on the site, you'll see many postings extolling the benefits of placeholders. The basic idea is that you put in question marks when you prepare your SQL to act as placeholders for values and then substitute in the values when you execute the statement.
In this case, since we (or at least I) don't know the number of elements in @array, we need to dynmaically construct a placeholder string containing the same number of question marks as there are values in the array. The perl "x" multiplication allows us to make as many question marks as there are values in the array and the join function allows us to join the question marks with commas:
my $p_str = join ',', ('?') x @array;
If you print out that placeholder string, you'll see that it contains as many question marks as there are in the array all separated by commas. We then put that into the SQL. If we were doing this with three values "a", "b", "c" instead of the array, the placeholder string would look like "?,?,?" and we'd use it like this:
my $sql = "SELECT foo FROM bar WHERE baz IN (?,?,?)";
my $sth = $dbh->prepare( $sql );
$sth->execute( "a", "b", "c");
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
Re: Changing foreach loop for a while loop
by Old_Gray_Bear (Bishop) on Dec 29, 2004 at 23:31 UTC
|
I rather suspect that the control structure change isn't going to help you. I'd be very curious to know how much time is being consumed by the elided lines ( . . . .) in your loop.
That said, here is one way -
while (@array)
{
my $info_element = shift @array;
$sql= "SELECT C58XX.CCLMyy, C58XX.CLINyy FROM C58XX
WHERE C58XX.CCLMyy=$info_element AND
C58XX.CLINyy=$X_LINE ";
....
}
(Premature Optimization is the root of all Evil ....)
----
I Go Back to Sleep, Now.
OGB
| [reply] [d/l] [select] |
Re: Changing foreach loop for a while loop
by nedals (Deacon) on Dec 30, 2004 at 01:30 UTC
|
Just a thought, depending on what else is in the block.
You may want to prepare your SQL statement, with placeholders, outside the loop
my $sql = "SELECT C58XX.CCLMyy, C58XX.CLINyy FROM C58XX
WHERE C58XX.CCLMyy=? AND C58XX.CLINyy=$X_LINE";
my $sth = $dbh->prepare($sql);
while (@array) {
$sth->execute($_);
....
}
| [reply] [d/l] |
Re: Changing foreach loop for a while loop
by kesterkester (Hermit) on Dec 29, 2004 at 23:34 UTC
|
If you're sure it's the foreach loop that's causing the slowdown, you could do something simple like:
my $n = 0;
while ( $n < scalar @array ) {
my $sql = "SELECT blah FROM blah WHERE blah = $array[$n++]
}
I'd be a little suprised if it was the foreach that was slowing you down, unless you have a monster @array. I'd suggest using Benchmark to compare the while and foreach loops.
--Kester | [reply] [d/l] |
Re: Changing foreach loop for a while loop
by TomDLux (Vicar) on Dec 30, 2004 at 16:13 UTC
|
Whether you use a 'for' or a 'while' loop, loop
overhead takes microseconds per iteration. Yes,
'while' loops can be faster when reading in files, because
they read in one line at a time, rather than reading in
the whole file before processing the lines.
But that doesn't apply here, you start off with an
array already in memory.
Consider that an sql query takes milli-seconds,
if not seconds or minutes --- far longer than loop
overhead.
Since you're looking at improving performance, the
first step is to profile .... type perldoc Devel::DProf
into a terminal window or search CPAN.org.
--
TTTATCGGTCGTTATATAGATGTTTGCA
| [reply] |