* We meant well but it turns out that the array unnest and join is actually very slow, as the join arguments do not get pushed down into the CTE (in Postgres 9/10 at least, later versions remove some of the optimization barriers in that specifc type of query) * This caused a seq scan on both device and device_port, and the query is executed many times during macsuck * The query is now rewritten to use ANY (macaddr[]) and without CTE, which seems to be around 20x faster
		
			
				
	
	
		
			50 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			50 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
package App::Netdisco::Util::PortMAC;
 | 
						|
 | 
						|
use Dancer qw/:syntax :script/;
 | 
						|
use Dancer::Plugin::DBIC 'schema';
 | 
						|
 | 
						|
use base 'Exporter';
 | 
						|
our @EXPORT = ();
 | 
						|
our @EXPORT_OK = qw/ get_port_macs /;
 | 
						|
our %EXPORT_TAGS = (all => \@EXPORT_OK);
 | 
						|
 | 
						|
=head1 NAME
 | 
						|
 | 
						|
App::Netdisco::Util::PortMAC
 | 
						|
 | 
						|
=head1 DESCRIPTION
 | 
						|
 | 
						|
Helper subroutine to support parts of the Netdisco application.
 | 
						|
 | 
						|
There are no default exports, however the C<:all> tag will export all
 | 
						|
subroutines.
 | 
						|
 | 
						|
=head1 EXPORT_OK
 | 
						|
 | 
						|
=head2 get_port_macs
 | 
						|
 | 
						|
Returns a Hash reference of C<< { MAC => IP } >> for all interface MAC
 | 
						|
addresses supplied as array reference
 | 
						|
 | 
						|
=cut
 | 
						|
 | 
						|
sub get_port_macs {
 | 
						|
    my ($fw_mac_list) = $_[0];
 | 
						|
    my $port_macs = {};
 | 
						|
    return {} unless ref [] eq ref $fw_mac_list and @{$fw_mac_list} >= 1;
 | 
						|
 | 
						|
    my $bindarray = [ { sqlt_datatype => "array" }, $fw_mac_list ];
 | 
						|
 | 
						|
    my $macs
 | 
						|
        = schema('netdisco')->resultset('Virtual::PortMacs')->search({},
 | 
						|
        { bind => [$bindarray, $bindarray], select => [ 'mac', 'ip' ], group_by => [ 'mac', 'ip' ] } );
 | 
						|
    my $cursor = $macs->cursor;
 | 
						|
    while ( my @vals = $cursor->next ) {
 | 
						|
        $port_macs->{ $vals[0] } = $vals[1];
 | 
						|
    }
 | 
						|
 | 
						|
    return $port_macs;
 | 
						|
}
 | 
						|
 | 
						|
1;
 |