3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-11-23 04:19:27 +01:00

Significant speed-up when invoking Factoids using DualIndexSQLiteObject as backend

This commit is contained in:
Pragmatic Software 2021-07-17 17:04:12 -07:00
parent e05cc6a33e
commit b154fe2b5b
2 changed files with 33 additions and 15 deletions

View File

@ -53,9 +53,8 @@ sub begin {
$self->{pbot}->{logger}->log("Opening $self->{name} database ($self->{filename})\n"); $self->{pbot}->{logger}->log("Opening $self->{name} database ($self->{filename})\n");
$self->{dbh} = DBI->connect( $self->{dbh} = DBI->connect("dbi:SQLite:dbname=$self->{filename}", undef, undef,
"dbi:SQLite:dbname=$self->{filename}", "", "", { AutoCommit => 0, RaiseError => 1, PrintError => 0, AutoInactiveDestroy => 1, sqlite_unicode => 1 }
{RaiseError => 1, PrintError => 0, AutoInactiveDestroy => 1, sqlite_unicode => 1}
) or die $DBI::errstr; ) or die $DBI::errstr;
eval { eval {
@ -88,6 +87,12 @@ sub load {
$self->create_cache; $self->create_cache;
} }
sub save {
my ($self) = @_;
return if not $self->{dbh};
$self->{dbh}->commit;
}
sub create_database { sub create_database {
my ($self) = @_; my ($self) = @_;
@ -158,6 +163,7 @@ sub trim_cache {
sub create_metadata { sub create_metadata {
my ($self, $columns) = @_; my ($self, $columns) = @_;
return if not $self->{dbh}; return if not $self->{dbh};
$self->{columns} = $columns; $self->{columns} = $columns;
@ -166,8 +172,6 @@ sub create_metadata {
my %existing = (); my %existing = ();
foreach my $col (@{$self->{dbh}->selectall_arrayref("PRAGMA TABLE_INFO(Stuff)")}) { $existing{$col->[1]} = $col->[2]; } foreach my $col (@{$self->{dbh}->selectall_arrayref("PRAGMA TABLE_INFO(Stuff)")}) { $existing{$col->[1]} = $col->[2]; }
$self->{dbh}->begin_work;
foreach my $col (sort keys %$columns) { foreach my $col (sort keys %$columns) {
unless (exists $existing{$col}) { $self->{dbh}->do("ALTER TABLE Stuff ADD COLUMN \"$col\" $columns->{$col}"); } unless (exists $existing{$col}) { $self->{dbh}->do("ALTER TABLE Stuff ADD COLUMN \"$col\" $columns->{$col}"); }
} }
@ -183,6 +187,7 @@ sub create_metadata {
sub levenshtein_matches { sub levenshtein_matches {
my ($self, $index1, $index2, $distance, $strictnamespace) = @_; my ($self, $index1, $index2, $distance, $strictnamespace) = @_;
my $comma = ''; my $comma = '';
my $result = ''; my $result = '';
@ -588,7 +593,6 @@ sub add {
eval { eval {
my $sth; my $sth;
$self->{dbh}->begin_work;
if (not $self->exists($index1, $index2)) { if (not $self->exists($index1, $index2)) {
$sth = $self->{dbh}->prepare('INSERT INTO Stuff (index1, index2) VALUES (?, ?)'); $sth = $self->{dbh}->prepare('INSERT INTO Stuff (index1, index2) VALUES (?, ?)');
@ -620,8 +624,6 @@ sub add {
$sth->bind_param($param++, $index2); $sth->bind_param($param++, $index2);
$sth->execute(); $sth->execute();
$self->{dbh}->commit;
# no errors updating SQL -- now we update cache # no errors updating SQL -- now we update cache
my ($lc_index1, $lc_index2) = (lc $index1, lc $index2); my ($lc_index1, $lc_index2) = (lc $index1, lc $index2);
$self->{cache}->{$lc_index1}->{_name} = $index1 if $index1 ne $lc_index1 and not exists $self->{cache}->{$lc_index1}->{_name}; $self->{cache}->{$lc_index1}->{_name} = $index1 if $index1 ne $lc_index1 and not exists $self->{cache}->{$lc_index1}->{_name};
@ -645,6 +647,7 @@ sub add {
$index1 = 'global' if $index1 eq '.*'; $index1 = 'global' if $index1 eq '.*';
$index2 = "\"$index2\"" if $index2 =~ / /; $index2 = "\"$index2\"" if $index2 =~ / /;
$self->{pbot}->{logger}->log("$self->{name}: [$index1]: $index2 added.\n") unless $quiet; $self->{pbot}->{logger}->log("$self->{name}: [$index1]: $index2 added.\n") unless $quiet;
$self->save unless $quiet;
return "$index2 added to $name1."; return "$index2 added to $name1.";
} }
@ -674,6 +677,8 @@ sub remove {
return "Error removing $name1: $@"; return "Error removing $name1: $@";
} }
$self->save unless $dont_save;
return "$name1 removed."; return "$name1 removed.";
} }
@ -700,6 +705,7 @@ sub remove {
return "Error removing $name2 from $name1: $@"; return "Error removing $name2 from $name1: $@";
} }
$self->save unless $dont_save;
return "$name2 removed from $name1."; return "$name2 removed from $name1.";
} }
@ -720,6 +726,7 @@ sub remove {
return "Error unsetting $data_index from $name2: $@"; return "Error unsetting $data_index from $name2: $@";
} }
$self->save unless $dont_save;
return "$name2.$data_index unset."; return "$name2.$data_index unset.";
} }
@ -764,18 +771,24 @@ sub set {
return "$self->{name} have no such metadata $key."; return "$self->{name} have no such metadata $key.";
} }
if (not defined $value) { $value = $self->get_data($index1, $index2, $key); } if (not defined $value) {
$value = $self->get_data($index1, $index2, $key);
}
else { else {
eval { eval {
my $sth = $self->{dbh}->prepare("UPDATE Stuff SET '$key' = ? WHERE index1 = ? AND index2 = ?"); my $sth = $self->{dbh}->prepare("UPDATE Stuff SET '$key' = ? WHERE index1 = ? AND index2 = ?");
$sth->execute($value, $index1, $index2); $sth->execute($value, $index1, $index2);
my ($lc_index1, $lc_index2) = (lc $index1, lc $index2); my ($lc_index1, $lc_index2) = (lc $index1, lc $index2);
if (exists $self->{cache}->{$lc_index1} if (exists $self->{cache}->{$lc_index1}
and exists $self->{cache}->{$lc_index1}->{$lc_index2} and exists $self->{cache}->{$lc_index1}->{$lc_index2}
and exists $self->{cache}->{$lc_index1}->{$lc_index2}->{$key}) { and exists $self->{cache}->{$lc_index1}->{$lc_index2}->{$key}) {
$self->{cache}->{$lc_index1}->{$lc_index2}->{$key} = $value; $self->{cache}->{$lc_index1}->{$lc_index2}->{$key} = $value;
} }
$self->save;
}; };
if ($@) { if ($@) {
@ -814,14 +827,18 @@ sub unset {
eval { eval {
my $sth = $self->{dbh}->prepare("UPDATE Stuff SET '$key' = ? WHERE index1 = ? AND index2 = ?"); my $sth = $self->{dbh}->prepare("UPDATE Stuff SET '$key' = ? WHERE index1 = ? AND index2 = ?");
$sth->execute(undef, $index1, $index2); $sth->execute(undef, $index1, $index2);
my ($lc_index1, $lc_index2) = (lc $index1, lc $index2); my ($lc_index1, $lc_index2) = (lc $index1, lc $index2);
if (exists $self->{cache}->{$lc_index1} if (exists $self->{cache}->{$lc_index1}
and exists $self->{cache}->{$lc_index1}->{$lc_index2} and exists $self->{cache}->{$lc_index1}->{$lc_index2}
and exists $self->{cache}->{$lc_index1}->{$lc_index2}->{$key}) { and exists $self->{cache}->{$lc_index1}->{$lc_index2}->{$key}) {
$self->{cache}->{$lc_index1}->{$lc_index2}->{$key} = undef; $self->{cache}->{$lc_index1}->{$lc_index2}->{$key} = undef;
} }
$self->save;
}; };
if ($@) { if ($@) {
@ -834,7 +851,6 @@ sub unset {
# nothing to do here for SQLite # nothing to do here for SQLite
# kept for compatibility with DualIndexHashObject # kept for compatibility with DualIndexHashObject
sub save { }
sub clear { } sub clear { }
1; 1;

View File

@ -66,7 +66,6 @@ sub initialize {
my $filename = $conf{filename}; my $filename = $conf{filename};
$self->{pbot} = $self->{pbot}; $self->{pbot} = $self->{pbot};
$self->{pbot}->{atexit}->register(sub { $self->save_factoids; return; });
$self->{storage} = PBot::DualIndexSQLiteObject->new(name => 'Factoids', filename => $filename, pbot => $self->{pbot}); $self->{storage} = PBot::DualIndexSQLiteObject->new(name => 'Factoids', filename => $filename, pbot => $self->{pbot});
@ -78,18 +77,21 @@ sub initialize {
$self->{pbot}->{registry}->add_default('text', 'factoids', 'max_channel_length', 20); $self->{pbot}->{registry}->add_default('text', 'factoids', 'max_channel_length', 20);
$self->load_factoids; $self->load_factoids;
# save and export factoids at exit
$self->{pbot}->{atexit}->register(sub { $self->save_factoids(1) });
} }
sub load_factoids { sub load_factoids {
my $self = shift; my ($self) = @_;
$self->{storage}->load; $self->{storage}->load;
$self->{storage}->create_metadata(\%factoid_metadata); $self->{storage}->create_metadata(\%factoid_metadata);
} }
sub save_factoids { sub save_factoids {
my $self = shift; my ($self, $export) = @_;
$self->{storage}->save; $self->{storage}->save;
$self->export_factoids; $self->export_factoids if $export;
} }
sub get_meta { sub get_meta {
@ -1239,7 +1241,7 @@ sub interpreter {
last_referenced_on => scalar gettimeofday, last_referenced_on => scalar gettimeofday,
last_referenced_in => $context->{from} || 'stdin', last_referenced_in => $context->{from} || 'stdin',
}; };
$self->{storage}->add($channel, $keyword, $update_data, 1, 1); $self->{storage}->add($channel, $keyword, $update_data, 1);
my $action; my $action;