I am trying to track pageviews in MySQL DB using the following query:
\"UPDATE $table SET pageviews = pageviews + 1 WHERE page_id = 1\"
This is fine
I would use memcached to store the count, and then sync it with the database on a cron...
// Increment
$page_id = 1;
$memcache = new Memcache();
$memcache->connect('localhost', 11211);
if (!$memcache->get('page_' . $page_id)) {
$memcache->set('page_' . $page_id, 1);
}
else {
$memcache->increment('page_' . $page_id, 1);
}
// Cron
if ($pageviews = $memcache->get('page_' . $page_id)) {
$sql = "UPDATE pages SET pageviews = pageviews + " . $pageviews . " WHERE page_id = " . $page_id;
mysql_query($sql);
$memcache->delete('page_' . $page_id);
}
You haven't specified the read or write rate to this table. MySQL can usually keep up quite well if you keep the indexing to an absolute minimum and the row size small. A table with a page ID and a counter column should be very fast most of the time.
InnoDB should be fine as well. MyISAM is liable to explode in the worst possible way if the system crashes or loses power during heavy write activity, it's not journaled and can't always be recovered. InnoDB is much more robust.
To get maximum performance from InnoDB, you'll want to tune your server according to the standard guidelines and benchmark it aggressively to be sure you got it right. Each OS has its quirks. Sometimes you can be missing out on a factor of two performance increase by not having the right setting.
If your tracking database is small, you might want to create an instance backed by a RAM disk and replicate it to another server with a regular HD. Since you're expecting extremely high write activity, if you can endure a small loss of data in the worst possible situation like a system crash, you could simply mysqldump
this database periodically to snapshot it. Dumping a memory-backed database with even a million rows should take only a minute and wouldn't interrupt writes due to MVCC.
I'd consider gathering raw hits with the fastest writing engine you have available:
INSERT INTO hits (page_id, hit_date) VALUES (:page_id, CURRENT_TIMESTAMP)
... and then running a periodical process, possibly a cron command line script, that would count and store the page count summary you need in an hourly or daily basis:
INSERT INTO daily_stats (page_id, num_hits, day)
SELECT page_id, SUM(hit_id)
FROM hits
WHERE hit_date='2012-11-29'
GROUP BY page_id
(Queries are mere examples, tweak to your needs)
Another typical solution is good old log parsing, feeding a script like AWStats with your web server's logs.
Clarification: My first suggestion is fairly similar to @fire's but I didn't get into storage details. The key point is to delay heavy processing and just the minimum amount of raw info in the fastest way.