Mysql 8: count(*) on INT primary is 13500 times slower than supposed to be. any innodb dev here?
Add INDEX(last_error_code), then do SELECT COUNT(*) FROM logos, it will run a lot faster because it will use the much smaller BTree for that secondary index.

SHOW TABLE STATUS LIKE 'logos' will give you an approximate count.

Why is the PK bloated?  InnoDB orders the data by the PRIMARY KEY; hence the PK, as an INDEX is essentially included in the data.  So to fetch a PK implies fetching the entire row.  (Caveat:  Bulky columns such as your texts and blobs are stored in a separate place, so they are not fetched when doing the COUNT(*).)

The Data+PK is in one B+Tree; each secondary index is in its own B+Tree.

Any "size" math (such as INT takes 4 bytes) needs to be multiplied by about 2 or 3 due to various overheads -- per column, per row, per block, etc.  And the block nature has its own overhead due to block splits.

If the entire table happens to be cached in RAM (that is, in the innodb_buffer_pool), then there won't be any I/O.  Still there is a non-trivial amount of CPU work to scan through your millions of rows.

I would guess that your table is slightly bigger than will fit in the buffer_pool.  So, every time you do that COUNT(*) it is competing with all other queries for room in the cache.  Not cool.

Note that the index I propose will take about 3GB, so it has a chance of being cached and perhaps even staying cached.  The first time (after a restart) you do the COUNT(*), it will be slow because of lots of I/O.  The second time (unless blocks have been bumped out of cache), it will be faster; perhaps ten times as fast.  That will probably be less than an hour, but more than a few seconds.

What is the value of innodb_buffer_pool_size?

How do others solve the sluggishness of COUNT(*)?  Have you noticed that search engines, if they say anything about 'how many', give you round numbers like "About 14,000,000 hits"?  That's one approach -- periodically get the exact number and round it off until you get around to checking again.

Or they have, say, daily subtotals.  Then the query SUMs up the daily counts.  This is much faster.  (But it only works for stuff that is continually coming in and not changing.)

Or ... (There are other techniques.)  What is your use case?

The idea of "random areas, plus extrapolation" probably has a lot of hassles; I would not embark on such.  Anyway, that is essentially what SHOW TABLE STATUS does.

MySQL 8.0.14 has Parallel scanning of by PRIMARY KEY (cf innodb_parallel_read_threads) for COUNT(*) w/o WHERE.  That will provide a little speedup for your original query.