To start off, the reason I'm asking this, is because I feel I have a database that - according to my own estimates - should have been killing the disks with massive I/O, because of indexes not fitting in memory, but in actuality it is still performing fine.
Let's start with the relevant table:
CREATE TABLE `search` (
`a` bigint(20) unsigned NOT NULL,
`b` int(10) unsigned NOT NULL,
`c` int(10) unsigned DEFAULT NULL,
`d` int(10) unsigned DEFAULT NULL,
`e` varchar(255) DEFAULT NULL,
`f` varchar(255) DEFAULT NULL,
`g` varchar(255) DEFAULT NULL,
`h` varchar(255) DEFAULT NULL,
`i` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
The a
column is a 8 byte digit that has the timestamp (in seconds) encoded into it. The table has a PARTITION BY RANGE (a)
, that separates the table into monthly partitions. This is because we only keep 24 months in the database, and the rest is purged.
The table grows by approximately 200 million rows per month; the full table contains about 5 billion rows.
The server it runs on has about 360GB of memory, and 300GB of that is reserved for MySQL. What I find interesting is that some time ago, disk utilization started going up a bit. Now, I believe this is because of certain indexes no longer fitting into memory, causing MySQL to load them from the disk, but this is just a guess; I'm unfamiliar with the internals of MySQL.
Is there a way to see what pages/blocks are loaded into memory at a given time, or for a specific query?
These are the three tables being actually used:
CREATE TABLE `search` (
`a` bigint(20) unsigned NOT NULL,
`b` int(10) unsigned NOT NULL,
`c` int(10) unsigned DEFAULT NULL,
`d` int(10) unsigned DEFAULT NULL,
`e` varchar(255) DEFAULT NULL,
`f` varchar(255) DEFAULT NULL,
`g` varchar(255) DEFAULT NULL,
`h` varchar(255) DEFAULT NULL,
`i` varchar(255) DEFAULT NULL,
KEY `a_idx` (`a`),
KEY `b_idx` (`b`),
KEY `c_idx` (`c`, `a`),
KEY `d_idx` (`d`, `a`),
KEY `e_idx` (`e`, `a`),
KEY `f_idx` (`f`, `a`),
KEY `g_idx` (`g`, `a`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `channels` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `clients` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`client_hash` varchar(4095) NOT NULL,
PRIMARY KEY (`id`),
KEY `hash_idx` (`client_hash`(255))
) ENGINE=InnoDB DEFAULT CHARSET=utf8
These are the queries that are currently running:
SELECT S.a,
S.b,
S.e,
S.f,
S.g,
S.h,
S.i,
C1.client_hash,
C2.name
FROM search S
LEFT JOIN clients C1
ON S.c = C1.id
LEFT JOIN channels C2
ON S.d = C2.id
WHERE S.e = "foo"
AND S.a >= 6409642363135721472
AND S.a <= 6443039964404908032
AND S.b >= 1492361157
AND S.b <= 1500137142
ORDER BY S.a DESC
LIMIT 50
SELECT S.a,
S.b,
S.e,
S.f,
S.g,
S.h,
S.i,
C1.client_hash,
C2.name
FROM search S
LEFT JOIN clients C1
ON S.c = C1.id
LEFT JOIN channels C2
ON S.d = C2.id
WHERE S.f = "bar"
AND S.a >= 6409642363135721472
AND S.b >= 1492361157
ORDER BY S.a DESC
LIMIT 50
SELECT S.a,
S.b,
S.e,
S.f,
S.g,
S.h,
S.i,
C1.client_hash,
C2.name
FROM search S
LEFT JOIN clients C1
ON S.c = C1.id
LEFT JOIN channels C2
ON S.d = C2.id
WHERE S.g = "baz"
AND S.a >= 6409642363135721472
AND S.b >= 1492361157
ORDER BY S.a DESC
LIMIT 50
SELECT S.a,
S.b,
S.e,
S.f,
S.g,
S.h,
S.i,
C1.client_hash,
C2.name
FROM search S
LEFT JOIN clients C1
ON S.c = C1.id
LEFT JOIN channels C2
ON S.d = C2.id
WHERE S.g LIKE "baz%"
AND S.a >= 6409642363135721472
AND S.b >= 1492361157
ORDER BY S.a DESC
LIMIT 50