#!/usr/bin/perl -w # Ausführungsplananalyse mehrerer SQL-Statements mithilfe von "EXPLAIN PLAN" # # Author: Uwe Schneider # # Diese Software ist UNSUPPORTET. # use strict; use FileHandle; use DBI; ####################################################################### my ($sth_plan); my ($statement_id); sub do_explain { my ($dbh,$sql) = @_; # Statischer Block unless ($sth_plan) { $statement_id = "SID.$$"; $sth_plan = $dbh->prepare(qq{ SELECT LPAD(' ',2*(LEVEL-1))||operation operation , options , object_name FROM plan_table START WITH id = 0 AND statement_id = '$statement_id' CONNECT BY PRIOR id = parent_id AND statement_id = '$statement_id' }) || die; } return if $sql =~ /EXPLAIN PLAN/i; $dbh->do(qq{ EXPLAIN PLAN SET STATEMENT_ID = '$statement_id' INTO plan_table FOR $sql }) || return; my ($operation, $options, $object_name); $sth_plan->execute() || die; while (($operation, $options, $object_name) = $sth_plan->fetchrow_array()) { printf ">> %s %s %s", $operation, $options || "", $object_name || ""; print " (O:$object_name)" if ($object_name); print "\n"; } $sth_plan->finish(); print "\n"; # Damit werden auch die plan_table-Einträge gelöscht. $dbh->rollback(); } ############################################################### sub usage_exit { print STDERR < Erzeugt zu jedem SQL-Statement den Ausführungsplan. Input: Tab-separierte Liste, erste Spalte: ausf. User, letzte Spalte: SQL-Text Output: Das gleiche, um Query-Plans angereichert. EOUSAGE die; } ####################################################################### # Feldseparator bei der Eingabe my ($SEP) = "\t"; my ($login) = shift || usage_exit(); my ($dbh) = DBI->connect("DBI:Oracle:",$login,) || die; $dbh->{'AutoCommit'} = 0; my ($user) = ($login =~ m|(\w+)/\w+@\w+|)[0]; my ($sql); # Schleife über die Eingabe while (<>) { print; # Wir setzen voraus, daß in der ersten Spalte der User und # in der letzten das SQL steht # Wenn der parsende User im Login-String steht... chop; my @a = split(/$SEP/); if (@a >= 2 && uc($a[0]) eq uc($user)) { do_explain($dbh,$a[$#a]); } } $dbh->disconnect();