According to this question, The answer is correct and made the queries better but does not solve the whole problem.
CREATE TABLE `USERS` (
`ID` char(255) COLLATE utf8_unicode_ci NOT NULL,
`NAME` char(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
There are only 5 rows inside the USERS table.
ID | NAME |
---|---|
C9XzpOxWtuh893z1GFB2sD4BIko2 | ... |
I2I7CZParyMatRKnf8NiByujQ0F3 | ... |
EJ12BBKcjAr2I0h0TxKvP7uuHtEg | ... |
VgqUQRn3W6FWAutAnHRg2K3RTvVL | ... |
M7jwwsuUE156P5J9IAclIkeS4p3L | ... |
CREATE TABLE `VISITS` (
`USER_ID` char(255) COLLATE utf8_unicode_ci NOT NULL,
`VISITED_IN` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
KEY `USER_ID` (`USER_ID`,`VISITED_IN`),
CONSTRAINT `VISITS_ibfk_1` FOREIGN KEY (`USER_ID`) REFERENCES `USERS` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
The indexes inside the VISITS table:
Keyname | Type | Unique | Packed | Column | Cardinality | Collation | Null | Comment |
---|---|---|---|---|---|---|---|---|
USER_ID | BTREE | No | No | USER_ID VISITED_IN |
3245 5283396 |
A A |
No No |
There are 5,740,266 rows inside the VISITS table:
C9XzpOxWtuh893z1GFB2sD4BIko2 = 4,359,264 profile visits
I2I7CZParyMatRKnf8NiByujQ0F3 = 1,237,286 profile visits
EJ12BBKcjAr2I0h0TxKvP7uuHtEg = 143,716 profile visits
VgqUQRn3W6FWAutAnHRg2K3RTvVL = 0 profile visits
M7jwwsuUE156P5J9IAclIkeS4p3L = 0 profile visits
The time is taken for queries: (Seconds will change according to the number of rows)
SELECT COUNT(*) FROM VISITS WHERE USER_ID = C9XzpOxWtuh893z1GFB2sD4BIko2
- Before applying Rick James' answer, The query took between 90 to 105 seconds
- After applying Rick James' answer, The query took between 55 to 65 seconds
SELECT COUNT(*) FROM VISITS WHERE USER_ID = I2I7CZParyMatRKnf8NiByujQ0F3
- Before applying Rick James' answer, The query took between 90 to 105 seconds
- After applying Rick James' answer, The query took between 20 to 30 seconds
SELECT COUNT(*) FROM VISITS WHERE USER_ID = EJ12BBKcjAr2I0h0TxKvP7uuHtEg
- Before applying Rick James' answer, The query took between 90 to 105 seconds After applying Rick James' answer, The query took between 4 to 8 seconds
SELECT COUNT(*) FROM VISITS WHERE USER_ID = VgqUQRn3W6FWAutAnHRg2K3RTvVL
- Before applying Rick James' answer, The query took between 90 to 105 seconds
- After applying Rick James' answer, The query took between 1 to 3 seconds
SELECT COUNT(*) FROM VISITS WHERE USER_ID = M7jwwsuUE156P5J9IAclIkeS4p3L
- Before applying Rick James' answer, The query took between 90 to 105 seconds
- After applying Rick James' answer, The query took between 1 to 3 seconds
As you can see before applying the index, It was taken between 90 to 105 seconds to count the visits of a specific user even if the user has a few rows (visits).
After applying the index things became better but the problem is:
- If I visit the
C9XzpOxWtuh893z1GFB2sD4BIko2
profile, It will take between 55 to 65 seconds to get profile visits. - If I visit the
I2I7CZParyMatRKnf8NiByujQ0F3
profile, It will take between 20 to 30 seconds to get profile visits. - Etc...
The user who has a few rows (visits) will be lucky because his profile will load faster.
I can ignore everything above and create a column inside the USERS table to count the user visits and increase it when catching a new visit without creating millions of rows but that will not be working with me because I allow the user to filter the visits like this:
Last 60 minutes
Last 24 hours
Last 7 days
Last 30 days
Last 6 months
Last 12 months
All-time
What should I do?