list-domain.php:

- replace get_domain_properties() calls with two SQL queries that fetch
  the domain data and count the number of mailboxes and aliases per domain.
  This change speeds up list-domain extremely on setups with lots of domains,
  mailboxes and aliases. The old code took several minutes on my test data
  (that's about 55000 mailboxes and their aliases), the new code only needs
  some seconds.
- $domain_properties now uses the domain name as index key instead of a
  serial number

templates/admin_list-domain.php:
- replace usage of $list_domains with $domain_properties
- change main loop to use the domain name as $domain_properties array key 
  instead of a serial number

upgrade.php:
- upgrade_655(): add index on domain column in mailbox and alias table.
  This speeds up list-domain from 14s to about 1s on my test data in MySQL
  (the 14s were _after_ the changes in list_domain.php)
- added _add_index() function to hide the database specific details in 
  upgrade functions

This commit should fix the performance problems reported on
http://sourceforge.net/forum/forum.php?thread_id=2343349&forum_id=676076



git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@655 a1433add-5e2c-0410-b055-b7f2511e0802
postfixadmin-2.3
Christian Boltz 16 years ago
parent 0e0bacb76e
commit 84a5203fe1

@ -40,24 +40,59 @@ if (authentication_has_role('global-admin')) {
$fUsername = "";
}
$list_all_domains = 0;
if (isset($admin_properties) && $admin_properties['domain_count'] == 'ALL') { # list all domains for superadmins
$list_domains = list_domains ();
$list_all_domains = 1;
} elseif (!empty($fUsername)) {
$list_domains = list_domains_for_admin ($fUsername);
} elseif ($is_superadmin) {
$list_domains = list_domains ();
$list_all_domains = 1;
} else {
$list_domains = list_domains_for_admin(authentication_get_username());
}
if (!empty ($list_domains))
{
for ($i = 0; $i < sizeof ($list_domains); $i++)
{
$domain_properties[$i] = get_domain_properties ($list_domains[$i]);
}
}
#}
if ($list_all_domains == 1) {
$where = " WHERE domain.domain != 'ALL' "; # TODO: the ALL dummy domain is annoying...
} else {
$list_domains = escape_string($list_domains);
$where = " WHERE domain.domain IN ('" . join("','", $list_domains) . "') ";
}
# fetch domain data and number of mailboxes
# (PgSQL requires the extensive GROUP BY statement, https://sourceforge.net/forum/message.php?msg_id=7386240)
$query = "
SELECT domain.* , COUNT( DISTINCT mailbox.username ) AS mailbox_count
FROM domain
LEFT JOIN mailbox ON domain.domain = mailbox.domain
$where
GROUP BY domain.domain, domain.description, domain.aliases, domain.mailboxes,
domain.maxquota, domain.quota, domain.transport, domain.backupmx, domain.created,
domain.modified, domain.active
ORDER BY domain.domain
";
$result = db_query($query);
while ($row = db_array ($result['result'])) {
$domain_properties[$row['domain']] = $row;
}
# fetch number of aliases
# doing this separate is much faster than doing it in one "big" query
$query = "
SELECT domain.domain, COUNT( DISTINCT alias.address ) AS alias_count
FROM domain
LEFT JOIN alias ON domain.domain = alias.domain
$where
GROUP BY domain.domain
ORDER BY domain.domain
";
$result = db_query($query);
while ($row = db_array ($result['result'])) {
# add number of aliases to $domain_properties array. mailbox aliases do not count.
$domain_properties [$row['domain']] ['alias_count'] = $row['alias_count'] - $domain_properties [$row['domain']] ['mailbox_count'];
}
include ("templates/header.php");
include ("templates/menu.php");

@ -27,7 +27,7 @@ if (!empty ($list_admins))
</div>
<?php
if (sizeof ($list_domains) > 0)
if (sizeof ($domain_properties) > 0)
{
print "<table id=\"admin_table\">\n";
print " <tr class=\"header\">\n";
@ -43,12 +43,13 @@ if (sizeof ($list_domains) > 0)
print " <td colspan=\"2\">&nbsp;</td>\n";
print " </tr>\n";
for ($i = 0; $i < sizeof ($list_domains); $i++)
# for ($i = 0; $i < sizeof ($domain_properties); $i++)
foreach(array_keys($domain_properties) as $i)
{
if ((is_array ($list_domains) and sizeof ($list_domains) > 0))
if ((is_array ($domain_properties) and sizeof ($domain_properties) > 0))
{
print " <tr class=\"hilightoff\" onMouseOver=\"className='hilighton';\" onMouseOut=\"className='hilightoff';\">\n";
print "<td><a href=\"list-virtual.php?domain=" . $list_domains[$i] . "\">" . $list_domains[$i] . "</a></td>";
print "<td><a href=\"list-virtual.php?domain=" . $domain_properties[$i]['domain'] . "\">" . $domain_properties[$i]['domain'] . "</a></td>";
print "<td>" . $domain_properties[$i]['description'] . "</td>";
print "<td>" . $domain_properties[$i]['alias_count'] . " / " . $domain_properties[$i]['aliases'] . "</td>";
print "<td>" . $domain_properties[$i]['mailbox_count'] . " / " . $domain_properties[$i]['mailboxes'] . "</td>";
@ -74,9 +75,9 @@ if (sizeof ($list_domains) > 0)
print "<td>$backupmx</td>";
print "<td>" . $domain_properties[$i]['modified'] . "</td>";
$active = ($domain_properties[$i]['active'] == 1) ? $PALANG['YES'] : $PALANG['NO'];
print "<td><a href=\"edit-active-domain.php?domain=" . $list_domains[$i] . "\">" . $active . "</a></td>";
print "<td><a href=\"edit-domain.php?domain=" . $list_domains[$i] . "\">" . $PALANG['edit'] . "</a></td>";
print "<td><a href=\"delete.php?table=domain&delete=" . $list_domains[$i] . "\" onclick=\"return confirm ('" . $PALANG['confirm_domain'] . $PALANG['pAdminList_admin_domain'] . ": " . $list_domains[$i] . "')\">" . $PALANG['del'] . "</a></td>";
print "<td><a href=\"edit-active-domain.php?domain=" . $domain_properties[$i]['domain'] . "\">" . $active . "</a></td>";
print "<td><a href=\"edit-domain.php?domain=" . $domain_properties[$i]['domain'] . "\">" . $PALANG['edit'] . "</a></td>";
print "<td><a href=\"delete.php?table=domain&delete=" . $domain_properties[$i]['domain'] . "\" onclick=\"return confirm ('" . $PALANG['confirm_domain'] . $PALANG['pAdminList_admin_domain'] . ": " . $domain_properties[$i]['domain'] . "')\">" . $PALANG['del'] . "</a></td>";
print "</tr>\n";
}
}

@ -222,6 +222,21 @@ function _drop_index ($table, $index) {
}
}
function _add_index($table, $indexname, $fieldlist) {
global $CONF;
$tabe = table_by_key ($table);
if ($CONF['database_type'] == 'mysql' || $CONF['database_type'] == 'mysqli' ) {
return "ALTER TABLE $table ADD INDEX `$indexname` ( `$fieldlist` )";
} elseif($CONF['database_type'] == 'pgsql') {
$pgindexname = $table . "_" . $indexname;
return "CREATE INDEX $pgindexname ON $table($fieldlist);"; # Index names are unique with a DB for PostgreSQL
} else {
echo "Sorry, unsupported database type " . $conf['database_type'];
exit;
}
}
function upgrade_1_mysql() {
// CREATE MYSQL DATABASE TABLES.
@ -1063,3 +1078,7 @@ function upgrade_504_mysql() {
db_query_parsed("ALTER TABLE `$table_mailbox` CHANGE `local_part` `local_part` VARCHAR( 255 ) {LATIN1} NOT NULL");
}
function upgrade_655() {
db_query_parsed(_add_index('mailbox', 'domain', 'domain'));
db_query_parsed(_add_index('alias', 'domain', 'domain'));
}

Loading…
Cancel
Save