Hello all. At the site where i am an administrator we have a large user gallery based on coppermine. You can see it here if you want :
http://www.dpgr.gr/usergalleries/index.php?cat=0The gallery has more than 117 000 photos and more than 20 000 page views per day.
We also have a dedicated dual Xeon server @ 3Ghz and 2Gb ram but the server was crashing almost 3 times per day. So i had to do something about it. I timed several parts of the code and finally located the most heavy queries. The good news is that i managed with some modifications to considerably decrease the page creation times. So lets start with the mainpage...
In our server the main page was created in something like 3 to 4 seconds. Very large time for a gallery with 20 000 page views per day. There were 2 main problems about it.
1) The stats display that say how many photos, albums, comments etc the gallery has took about 0,7 seconds. So i decided to remove the code that gathers the stats from the index.php and place it in a seperate .php file which you can either run manually when you want the stats to be updated or make it a cron job to automatically run every 1 or 4 hours or whatever period you want (but dont do it every minute!).
Here is the modifications you need to do:
1a) Open index.php and comment the following lines :
/*$result = cpg_db_query("SELECT count(*) FROM {$CONFIG['TABLE_ALBUMS']} as a WHERE 1" . $album_filter);
$nbEnr = mysql_fetch_array($result);
$album_count = $nbEnr[0];
......................................... More code here ..................................
$nbEnr = mysql_fetch_array($result);
$hit_count = (int)$nbEnr[0];
mysql_free_result($result);*/
1b) Immediatly after that add the code:
$exec = mysql_query("SELECT * FROM gallery_stats LIMIT 0,1") or die(mysql_error());
$data = mysql_fetch_assoc($exec);
$album_count = $data['albums'];
$picture_count = $data['pictures'];
$comment_count = $data['comments'];
$cat_count = $data['categories'];
$hit_count = $data['views'];
Save and upload the file. 2 more steps remaining ...
1c) No go to your database with phpmyadmin and run the following SQL:
CREATE TABLE `gallery_stats` (
`stat_id` tinyint(3) unsigned NOT NULL auto_increment,
`albums` bigint(20) NOT NULL default '0',
`pictures` bigint(20) NOT NULL default '0',
`categories` bigint(20) NOT NULL default '0',
`comments` bigint(20) NOT NULL default '0',
`views` bigint(20) NOT NULL default '0',
PRIMARY KEY (`stat_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
--
-- Dumping data for table `gallery_stats`
--
INSERT INTO `gallery_stats` VALUES (1, 0, 0, 0, 0, 0);
This will create a table that will hold the stats that index.php will retrieve and display and that the following file (gallery_stats.php) will generate...
1d) Create a php file gallery_stats.php and put the following code in it
<?php
$db_name = "yourDB";
$db_user = "yourUser";
$db_passwd = "yourPass";
$db_server = "localhost";
mysql_connect("localhost", $db_user, $db_passwd);
mysql_select_db($db_name);
$CONFIG['TABLE_ALBUMS'] = "usercpg11d_albums";
$CONFIG['TABLE_PICTURES'] = "usercpg11d_pictures";
$CONFIG['TABLE_COMMENTS'] = "usercpg11d_comments";
$CONFIG['TABLE_CATEGORIES'] = "usercpg11d_categories";
$result = mysql_query("SELECT count(*) FROM {$CONFIG['TABLE_ALBUMS']} as a WHERE 1" . $album_filter);
$nbEnr = mysql_fetch_array($result);
$album_count = $nbEnr[0];
mysql_free_result($result);
$sql = "SELECT count(*) FROM {$CONFIG['TABLE_PICTURES']} as p " . 'LEFT JOIN ' . $CONFIG['TABLE_ALBUMS'] . ' as a ' . 'ON a.aid=p.aid ' . 'WHERE 1' . $pic_filter . ' AND approved=\'YES\'';
$result = mysql_query($sql);
$nbEnr = mysql_fetch_array($result);
$picture_count = $nbEnr[0];
mysql_free_result($result);
$sql = "SELECT count(*) FROM {$CONFIG['TABLE_COMMENTS']} as c " . 'LEFT JOIN ' . $CONFIG['TABLE_PICTURES'] . ' as p ' . 'ON c.pid=p.pid ' . 'LEFT JOIN ' . $CONFIG['TABLE_ALBUMS'] . ' as a ' . 'ON a.aid=p.aid ' . 'WHERE 1' . $pic_filter;
$result = mysql_query($sql);
$nbEnr = mysql_fetch_array($result);
$comment_count = $nbEnr[0];
mysql_free_result($result);
$sql = "SELECT count(*) FROM {$CONFIG['TABLE_CATEGORIES']} WHERE 1";
$result = mysql_query($sql);
$nbEnr = mysql_fetch_array($result);
$cat_count = $nbEnr[0] - $HIDE_USER_CAT;
mysql_free_result($result);
$sql = "SELECT sum(hits) FROM {$CONFIG['TABLE_PICTURES']} as p " . 'LEFT JOIN ' . $CONFIG['TABLE_ALBUMS'] . ' as a ' . 'ON p.aid=a.aid ' . 'WHERE 1' . $pic_filter;
$result = mysql_query($sql);
$nbEnr = mysql_fetch_array($result);
$hit_count = (int)$nbEnr[0];
mysql_free_result($result);
mysql_query("UPDATE gallery_stats SET albums=$album_count, categories=$cat_count, comments=$comment_count, views=$hit_count, pictures=$picture_count WHERE stat_id=1") or die(mysql_error());
mysql_close();
?>
Just replace the lines with th db connection data with your settings as well the table names. Now save the file and upload it. As i said you can either run it manually ormake it a cron job.
Ok. This is maybe too much for some so lets see another easier modification you can do.
If you have lots of photos and you have enabled the random photos box it will greatly increase your page creation time. So you can either disable it from the admin panel or make the following modification that will decrease the query time from 1,4 secs to about 0,3 :
2a) Open /include/functions.inc.php and find the line :
$query = "SELECT $select_columns FROM {$CONFIG['TABLE_PICTURES']} WHERE approved = 'YES' $META_ALBUM_SET ORDER BY RAND() LIMIT $limit2";
Replace it with the following lines :
$q = "SELECT pid FROM {$CONFIG['TABLE_PICTURES']} WHERE approved = 'YES' $META_ALBUM_SET ORDER BY RAND() LIMIT $limit2";
$ex = mysql_query($q) or die(mysql_error());
$pid_array = array();
while($d = mysql_fetch_assoc($ex)){
$pid_array[] = $d['pid'];
}
$pid_string = implode(", ", $pid_array);
$query = "SELECT $select_columns FROM {$CONFIG['TABLE_PICTURES']} WHERE pid IN ($pid_string)";
Save and upload the file. We are done for the mainpage. With these modifications i was able to drop the page creation time of index.php from 3 seconds to 1.
Now another thing that really slows down coppermine on large galleries is top viewed photos. When you visit the top views album and from there you click to see a photo the page will be created in 4 to 5 seconds. The reason for this is the way the filmstrip is generated trying to figure out what is the previous and next photos. So lets drop this time to around 0,5 seconds doing the following modifications:
3a) find the line :
$query ="SELECT COUNT(*) from {$CONFIG['TABLE_PICTURES']} WHERE approved = 'YES' AND hits > 0 $META_ALBUM_SET $keyword";
and replace with the following:
$cat >= 10000 ? $hit_limit = 0 : $hit_limit = 310;
$query ="SELECT COUNT(*) from {$CONFIG['TABLE_PICTURES']} WHERE approved = 'YES' AND hits > $hit_limit $META_ALBUM_SET $keyword";
3b) find the line:
$query = "SELECT $select_columns FROM {$CONFIG['TABLE_PICTURES']} WHERE approved = 'YES'AND hits > 0 $META_ALBUM_SET $keyword ORDER BY hits DESC, filename $limit";
replace with the following :
$query = "SELECT $select_columns FROM {$CONFIG['TABLE_PICTURES']} WHERE approved = 'YES'AND hits > $hit_limit $META_ALBUM_SET $keyword ORDER BY hits DESC, filename $limit";
The only change you need to do is replace 303 with your own number. To find what the number for your gallery should be do this: Go to the 10th page of the top views album and see how much views the last photo of this page has. Now this is the number you should use instead of 303.
The downside of this modification is that you limit the top views album to the first 10 pages. But when you consider that the page creation time drops to 1/10th of original i think its a fair trade. After all, top views is about top, not bottom

So finishing up, i would like to make some things clear.
1) Those solutions may not be the best ones ... but they work.
2) I am not trying to say that the coppermine gallery is not good. I am just trying to help people that have similar proplems with me and maybe offer some ideas for future versions of coppermine.
Hope this helped, try the modifications and tell me what you think.