From 84a5203fe1c801283a5d62a1e49aca418ca92959 Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Tue, 12 May 2009 22:19:39 +0000 Subject: [PATCH] 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 --- list-domain.php | 55 +++++++++++++++++++++++++++------ templates/admin_list-domain.php | 15 ++++----- upgrade.php | 19 ++++++++++++ 3 files changed, 72 insertions(+), 17 deletions(-) diff --git a/list-domain.php b/list-domain.php index edbf53ac..c46ccc8e 100644 --- a/list-domain.php +++ b/list-domain.php @@ -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"); diff --git a/templates/admin_list-domain.php b/templates/admin_list-domain.php index db60aea7..b01e08b9 100644 --- a/templates/admin_list-domain.php +++ b/templates/admin_list-domain.php @@ -27,7 +27,7 @@ if (!empty ($list_admins)) 0) +if (sizeof ($domain_properties) > 0) { print "\n"; print " \n"; @@ -43,12 +43,13 @@ if (sizeof ($list_domains) > 0) print " \n"; print " \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 " \n"; - print ""; + print ""; print ""; print ""; print ""; @@ -74,9 +75,9 @@ if (sizeof ($list_domains) > 0) print ""; print ""; $active = ($domain_properties[$i]['active'] == 1) ? $PALANG['YES'] : $PALANG['NO']; - print ""; - print ""; - print ""; + print ""; + print ""; + print ""; print "\n"; } } diff --git a/upgrade.php b/upgrade.php index 9aa4eaf6..ef63d51e 100644 --- a/upgrade.php +++ b/upgrade.php @@ -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')); +}
 
" . $list_domains[$i] . "" . $domain_properties[$i]['domain'] . "" . $domain_properties[$i]['description'] . "" . $domain_properties[$i]['alias_count'] . " / " . $domain_properties[$i]['aliases'] . "" . $domain_properties[$i]['mailbox_count'] . " / " . $domain_properties[$i]['mailboxes'] . "$backupmx" . $domain_properties[$i]['modified'] . "" . $active . "" . $PALANG['edit'] . "" . $PALANG['del'] . "" . $active . "" . $PALANG['edit'] . "" . $PALANG['del'] . "