Files
netdisco/lib/App/Netdisco/Util/PortMAC.pm
Christian Ramseyer 031c3e6d95 Optimize PortMAC query
* 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
2020-01-31 10:32:02 +01:00

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;