added some performance enhancements to grouping lookups

This commit is contained in:
JT Smith 2004-07-06 01:33:44 +00:00
parent fbd0fa7efa
commit 819fde84b3
2 changed files with 44 additions and 26 deletions

View file

@ -52,6 +52,9 @@
- Added additional debugging to WebGUI::SQL. - Added additional debugging to WebGUI::SQL.
- Added a better user search mechanism, which works well even with 100,000 - Added a better user search mechanism, which works well even with 100,000
users. users.
- Made some minor changes to grouping lookups that resulted in an average of
14 less database queries per page when in admin mode which results in a 30%
performance gain while in admin mode.
6.0.3 6.0.3

View file

@ -233,8 +233,19 @@ sub getGroupsForUser {
my $clause = "and expireDate>".time() if ($withoutExpired); my $clause = "and expireDate>".time() if ($withoutExpired);
if ($userId eq "") { if ($userId eq "") {
return []; return [];
} elsif ($session{gotGroupsForUser}{$userId} == 1) {
my @groups;
foreach my $gid (keys %{$session{isInGroup}{$userId}}) {
push(@groups,$gid);
}
return \@groups;
} else { } else {
return WebGUI::SQL->buildArrayRef("select groupId from groupings where userId=$userId $clause"); my @groups = WebGUI::SQL->buildArray("select groupId from groupings where userId=$userId $clause");
foreach my $gid (@groups) {
$session{isInGroup}{$userId}{$gid} = 1;
}
$session{gotGroupsForUser}{$userId} = 1;
return \@groups;
} }
} }
@ -264,7 +275,9 @@ sub getGroupsInGroup {
my $groupId = shift; my $groupId = shift;
my $isRecursive = shift; my $isRecursive = shift;
my $loopCount = shift; my $loopCount = shift;
my $groups = WebGUI::SQL->buildArrayRef("select groupId from groupGroupings where inGroup=$groupId"); my $groupsLookedUp = shift;
my $extraWhere = "and groupId not in (".join(",",@{$groupsLookedUp}).")" if (defined @{$groupsLookedUp});
my $groups = WebGUI::SQL->buildArrayRef("select groupId from groupGroupings where inGroup=$groupId $extraWhere");
if ($isRecursive) { if ($isRecursive) {
$loopCount++; $loopCount++;
if ($loopCount > 99) { if ($loopCount > 99) {
@ -273,7 +286,7 @@ sub getGroupsInGroup {
} }
my @groupsOfGroups = @$groups; my @groupsOfGroups = @$groups;
foreach my $group (@$groups) { foreach my $group (@$groups) {
my $gog = getGroupsInGroup($group,1,$loopCount); my $gog = getGroupsInGroup($group,1,$loopCount,\@groupsOfGroups);
push(@groupsOfGroups, @$gog); push(@groupsOfGroups, @$gog);
} }
return \@groupsOfGroups; return \@groupsOfGroups;
@ -335,29 +348,31 @@ The user that you wish to verify against the group. Defaults to the currently lo
=cut =cut
sub isInGroup { sub isInGroup {
my ($gid, $uid, @data, %group, $groupId); my (@data, %group, $groupId);
($gid, $uid) = @_; my ($gid, $uid, $secondRun) = @_;
$gid = 3 unless (defined $gid); $gid = 3 unless (defined $gid);
$uid = $session{user}{userId} if ($uid eq ""); $uid = $session{user}{userId} if ($uid eq "");
### The following several checks are to increase performance. If this section were removed, everything would continue to work as normal. ### The following several checks are to increase performance. If this section were removed, everything would continue to work as normal.
return 1 if ($gid == 7); # everyone is in the everyone group return 1 if ($gid == 7); # everyone is in the everyone group
return 1 if ($gid == 1 && $uid == 1); # visitors are in the visitors group return 1 if ($gid == 1 && $uid == 1); # visitors are in the visitors group
return 0 if ($gid != 1 && $uid == 1); # visitors can't be in any group execpt the visitors group return 0 if ($gid != 1 && $uid == 1); # visitors can't be in any group except the visitors group
return 1 if ($gid==2 && $uid != 1); # if you're not a visitor, then you're a registered user return 1 if ($gid==2 && $uid != 1); # if you're not a visitor, then you're a registered user
### Look to see if we've already looked up this group. ### Look to see if we've already looked up this group.
if ($session{isInGroup}{$gid}{$uid} == 1) { if ($session{isInGroup}{$uid}{$gid} == 1) {
return 1; return 1;
} elsif ($session{isInGroup}{$gid}{$uid} eq "0") { } elsif ($session{isInGroup}{$uid}{$gid} eq "0") {
return 0; return 0;
} }
### Lookup the actual groupings. ### Lookup the actual groupings.
my $groups = WebGUI::Grouping::getGroupsForUser($uid,1); unless ($secondRun) { # don't look up user groups if we've already done it once.
foreach (@{$groups}) { my $groups = WebGUI::Grouping::getGroupsForUser($uid,1);
$session{isInGroup}{$_}{$uid} = 1; foreach (@{$groups}) {
} $session{isInGroup}{$uid}{$_} = 1;
if ($session{isInGroup}{$gid}{$uid} == 1) { }
return 1; if ($session{isInGroup}{$uid}{$gid} == 1) {
} return 1;
}
}
### Get data for auxillary checks. ### Get data for auxillary checks.
tie %group, 'Tie::CPHash'; tie %group, 'Tie::CPHash';
%group = WebGUI::SQL->quickHash("select karmaThreshold,ipFilter,scratchFilter,databaseLinkId,dbQuery,dbCacheTimeout from groups where groupId='$gid'"); %group = WebGUI::SQL->quickHash("select karmaThreshold,ipFilter,scratchFilter,databaseLinkId,dbQuery,dbCacheTimeout from groups where groupId='$gid'");
@ -371,7 +386,7 @@ sub isInGroup {
my @ips = split(";",$group{ipFilter}); my @ips = split(";",$group{ipFilter});
foreach my $ip (@ips) { foreach my $ip (@ips) {
if ($session{env}{REMOTE_ADDR} =~ /^$ip/) { if ($session{env}{REMOTE_ADDR} =~ /^$ip/) {
$session{isInGroup}{$gid}{$uid} = 1; $session{isInGroup}{$uid}{$gid} = 1;
return 1; return 1;
} }
} }
@ -386,7 +401,7 @@ sub isInGroup {
foreach my $var (@vars) { foreach my $var (@vars) {
my ($name, $value) = split(/\=/,$var); my ($name, $value) = split(/\=/,$var);
if ($session{scratch}{$name} eq $value) { if ($session{scratch}{$name} eq $value) {
$session{isInGroup}{$gid}{$uid} = 1; $session{isInGroup}{$uid}{$gid} = 1;
return 1; return 1;
} }
} }
@ -400,7 +415,7 @@ sub isInGroup {
($karma) = WebGUI::SQL->quickHash("select karma from users where userId='$uid'"); ($karma) = WebGUI::SQL->quickHash("select karma from users where userId='$uid'");
} }
if ($karma >= $group{karmaThreshold}) { if ($karma >= $group{karmaThreshold}) {
$session{isInGroup}{$gid}{$uid} = 1; $session{isInGroup}{$uid}{$gid} = 1;
return 1; return 1;
} }
} }
@ -419,13 +434,13 @@ sub isInGroup {
} else { } else {
my ($result) = $sth->array; my ($result) = $sth->array;
if ($result == 1) { if ($result == 1) {
$session{isInGroup}{$gid}{$uid} = 1; $session{isInGroup}{$uid}{$gid} = 1;
if ($group{dbCacheTimeout} > 0) { if ($group{dbCacheTimeout} > 0) {
WebGUI::Grouping::deleteUsersFromGroups([$uid],[$gid]); WebGUI::Grouping::deleteUsersFromGroups([$uid],[$gid]);
WebGUI::Grouping::addUsersToGroups([$uid],[$gid],$group{dbCacheTimeout}); WebGUI::Grouping::addUsersToGroups([$uid],[$gid],$group{dbCacheTimeout});
} }
} else { } else {
$session{isInGroup}{$gid}{$uid} = 0; $session{isInGroup}{$uid}{$gid} = 0;
WebGUI::Grouping::deleteUsersFromGroups([$uid],[$gid]) if ($group{dbCacheTimeout} > 0); WebGUI::Grouping::deleteUsersFromGroups([$uid],[$gid]) if ($group{dbCacheTimeout} > 0);
} }
} }
@ -434,20 +449,20 @@ sub isInGroup {
WebGUI::ErrorHandler::warn("Database query for group ID $gid must use 'select 1'"); WebGUI::ErrorHandler::warn("Database query for group ID $gid must use 'select 1'");
} }
$dbLink->disconnect; $dbLink->disconnect;
return 1 if ($session{isInGroup}{$gid}{$uid}); return 1 if ($session{isInGroup}{$uid}{$gid});
} }
} }
} }
### Check for groups of groups. ### Check for groups of groups.
$groups = WebGUI::Grouping::getGroupsInGroup($gid,1); my $groups = WebGUI::Grouping::getGroupsInGroup($gid,1);
foreach (@{$groups}) { foreach (@{$groups}) {
$session{isInGroup}{$_}{$uid} = isInGroup($_, $uid); $session{isInGroup}{$uid}{$_} = isInGroup($_, $uid, 1);
if ($session{isInGroup}{$_}{$uid}) { if ($session{isInGroup}{$uid}{$_}) {
$session{isInGroup}{$gid}{$uid} = 1; # cache current group also so we don't have to do the group in group check again $session{isInGroup}{$uid}{$gid} = 1; # cache current group also so we don't have to do the group in group check again
return 1; return 1;
} }
} }
$session{isInGroup}{$gid}{$uid} = 0; $session{isInGroup}{$uid}{$gid} = 0;
return 0; return 0;
} }