From 59e2856993b61b2b421de708654a6aa6a3224eb7 Mon Sep 17 00:00:00 2001 From: Andreas Roussos Date: Tue, 1 Aug 2023 20:49:55 +0200 Subject: [PATCH] Bug 21828: build $bib_heading_fields only once per invocation In UNIMARC instances, the run time of link_bibs_to_authorities.pl can be reduced by up to 80% and the number of DBI calls can be reduced by up to 90% with a very simple fix that optimises the constructor of the C4::Heading::UNIMARC object. Currently, the constructor resets the $bib_heading_fields hash *in each invocation* (i.e. for every field the bibliographic record contains), then populating it again with the results fetched from the database! This is inefficient. The patch/fix is trivial: we take advantage of the fact that $bib_heading_fields is declared at the top of the C4::Heading::UNIMARC module and is thus a package variable that is in scope for the entire execution of the program (more info here: https://stackoverflow.com/q/75317862). Placing the section that generates the $bib_heading_fields hash inside a "unless ( defined $bib_heading_fields )" code block is enough to cause a significant reduction in the number of "expensive" SQL SELECT queries that must be run. Test plan: 0) Have a UNIMARC instance with some sample data (the KTD one will do just fine for this experiment). 1) Run the following commands: $ ktd --shell k$ DBI_PROFILE=1 ./misc/link_bibs_to_authorities.pl -t Observe the output from the script and the DBI profiling info. [You may want to play with different DBI_PROFILE levels (such as 2, 4, 6, 8, etc.) to see what's going on under the hood DBI-wise, for reference see: https://metacpan.org/pod/DBI::Profile] 2) Apply this patch. 3) Rerun the script from step 1), it should run a lot faster! Signed-off-by: David Nind --- C4/Heading/UNIMARC.pm | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/C4/Heading/UNIMARC.pm b/C4/Heading/UNIMARC.pm index 9767f751a7..a0a8a3edda 100644 --- a/C4/Heading/UNIMARC.pm +++ b/C4/Heading/UNIMARC.pm @@ -68,19 +68,21 @@ my $bib_heading_fields; sub new { my $class = shift; - my $dbh = C4::Context->dbh; - my $sth = $dbh->prepare( - "SELECT tagfield, authtypecode - FROM marc_subfield_structure - WHERE frameworkcode = '' AND authtypecode <> ''" - ); - $sth->execute(); - $bib_heading_fields = {}; - while ( my ( $tag, $auth_type ) = $sth->fetchrow ) { - $bib_heading_fields->{$tag} = { - auth_type => $auth_type, - subfields => 'abcdefghjklmnopqrstvxyz', - }; + unless ( defined $bib_heading_fields ) { + my $dbh = C4::Context->dbh; + my $sth = $dbh->prepare( + "SELECT tagfield, authtypecode + FROM marc_subfield_structure + WHERE frameworkcode = '' AND authtypecode <> ''" + ); + $sth->execute(); + $bib_heading_fields = {}; + while ( my ( $tag, $auth_type ) = $sth->fetchrow ) { + $bib_heading_fields->{$tag} = { + auth_type => $auth_type, + subfields => 'abcdefghjklmnopqrstvxyz', + }; + } } return bless {}, $class; -- 2.30.2