-1

I've been analysing my website's performance using Google PageSpeed Insights, and the main issue it's reporting is slow server response times, which seem to average around 1.5 - 2 seconds. Google recommend trying to achieve 200ms, so I'm way off.

What I've established is that the queries to retrieve the data from the database are causing quite significant performance issues. My website makes extensive use of caching to retrieve the sections of the website. The entire webpage can usually be generated from 5 database queries from the cache table.

When I hard-code my return value to this (note the 'This is a test' selection):

$sql = "SELECT 'This is a test' 
        FROM cache 
        WHERE url = ?
         AND language = ?
         AND currency = ?";
$stmt = $conn->prepare($sql);
if (!$stmt) {
    ThrowDBError($conn, $stmt, $sql);
}
$stmt->bind_param('sss', $url, $language, $currency);
if (!$stmt->execute()) {
    ThrowDBError($conn, $stmt, $sql);
}
$stmt->bind_result($cache);
$stmt->fetch();
$stmt->close();

The server response speed drops to 0.5 seconds. When I put it back to select the actual data column page_body, like this:

$sql = "SELECT page_body 
        FROM cache_copy 
        WHERE url = ?
         AND language = ?
         AND currency = ?";

$stmt = $conn->prepare($sql);
if (!$stmt) {
    ThrowDBError($conn, $stmt, $sql);
}
$stmt->bind_param('sss', $url, $language, $currency);
if (!$stmt->execute()) {
    ThrowDBError($conn, $stmt, $sql);
}
$stmt->bind_result($cache);
$stmt->fetch();
$stmt->close();

The the server response time jumps consistently to 1.5 - 2 seconds for the 5 queries the website makes to the cache table.

The cache table only contains 8,000 rows and I think I've correctly indexed it. The column page_body is a mediumtext - does anyone know of performance-related issues using mediumtext? I just can't figure why it would add 1.5 seconds to the load time.

Here is the DDL for the cache table:

CREATE TABLE `cache` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(255) NOT NULL,
  `language` varchar(2) NOT NULL,
  `currency` varchar(3) NOT NULL,
  `page_body` mediumtext NOT NULL,
  `cached_time` datetime NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `url, language, currency` (`url`,`language`,`currency`) USING BTREE,
  KEY `cached_time` (`cached_time`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Any ideas? Many thanks

BigMeaty
  • 9
  • 3
  • If you have to run 5 queries to generate 1 page it's reasonable that it takes this long.. There's probably nothing wrong with your code, but poor approach to caching is used.. In my experience caching is done on web server and shared between clients.. On db side views are used to automatically cache queries.. Sometimes you need to use load ballancer if you see high cpu on web server.. A lot of optimization is on front end js/css/images via browser gzip compression and caching.. Also check this out https://stackoverflow.com/a/7875699/3254405 – boateng Dec 04 '17 at 22:30
  • Thanks for your reply. In my OP I tested running 5 queries which returns hard-coded text ('This is a test') and it made no difference to the response time. The issue seems to be returning actual data, rather than overhead of performing the queries themselves. The issue seems to be when I get 'real' data from the table. – BigMeaty Dec 04 '17 at 22:54
  • 1
    As an additional test, I've duplicated a table used to store reviews which uses varchar (1000) for the review comment. On the duplicate table I change the type to mediumtext. Fast response with varchar, slow with mediumtext. The problem definitely seems to lie with using mediumtext as the datatype. – BigMeaty Dec 04 '17 at 23:05

1 Answers1

0

How many rows does it return? If it returning only 1 row, it should be well under 200ms.

Oh! Is see the problem. You are using MyISAM. Don't. Switch to InnoDB.

If the real table is like cache, you will get virtually the same speed from it. I suggest your get rid of the cache.

Rick James
  • 135,179
  • 13
  • 127
  • 222
  • The issue is due to a known limitation of mysqli, as explained here: https://bugs.php.net/bug.php?id=51386 The solution is to use store_result(), as shown here: if (!$stmt->execute()) { ThrowDBError($conn, $stmt, $sql); } $stmt->store_result(); $stmt->bind_result($cache); – BigMeaty Dec 06 '17 at 11:20