My wp_options table only had about 235 rows of data. I tried indexing the table, but it didn't help.
Turns out that about 150 transient options had been inserted into the table, but hadn't been automatically deleted.
I don't know if it is related or not, but I'd been looking through my /var/log/apache2/access.log files and noticed that multiple (presumably compromised) Amazon Web Services servers (IP addresses beginning with 54.X.X.X and 32.X.X.X) had been attempting to exploit /~web-root-dir/xmlrpc.php.
After some troubleshooting, I queried the wp_options table for option names that contained "transient"
select * from wp_options where option_name like '%transient%';
One of the fields returned from this query is 'option_value' which has a datatype of LONGTEXT. According to the mySQL docs, a LONGTEXT field (for each row) can hold up to 4-Gigabytes of data.
When I executed the query, some of the rows (remember were working with those containing "transient") had massive amounts of data in the option_value field. Looking through the results, I also saw what looked like attempts to inject commands into the wp-cron process with the hopes they would be executed during the cron cycle(s).
My solution was to delete all of the "transient" rows. This will not hurt the server since "transient" rows will automatically repopulate (if they are supposed to be there).
After doing this, the server was once again responsive.
Query to delete these rows:
DELETE from wp_options where option_name like '%transient%';
I've added the AWS IP address /8 superblocks to my firewall, too (-: