Easy MySQL Performance Tips

Yes, I’m still trying to squeeze more performance out of MySQL. And since small changes to a query can make a big difference in performance…

Here are two really easy things to be aware of:

  • Never do a COUNT(*) (or anything *, says Zach). Instead, replace the * with the name of the column you’re searching against (and is hopefully indexed). That way some queries can execute entirely in the keycache (while * forces MySQL to read every matching row from the table).
  • When joining two large tables, but only searching against one, put the join statement at the end. Why join the two entire tables when you only have to join the matching rows?

I mention these because, well, I’ve known them forever, but upon seeing them again I realized I hadn’t really obeyed those simple rules in some of my queries.

Separately, there’s some pretty good info on what server variables affect what at mysqlperformanceblog too.

mysql, optimization, query optimization, performance, tips

5 Comments to “Easy MySQL Performance Tips”

  1. Unfortunately you are incorrect with regards to count(*); Zach’s article is correct.

    Why? count(*) is optimised by MySQL. The table descriptor is used without the need to read any table records in the case of count star with no where condition, and an index is used if possible if there is a where condition. Doing a count on an appropriately indexed column is fine too, as Zach notes, however there is the risk that should the choice of indices be changed in the future that the counted column is no longer optimal and there is then a big hit that may go unnoticed. So count(*) SHOULD be used.

    It is fair to say that selecting of * is generally a bad idea for queries that return rows as most often then returns more data than is needed, taking more time in the process. For non performance critical queries using * is arguably OK and has advantages of reduced maintenance.

    Using * during early stages of development may be justified on the basis that it may speed development if the database schema is still in flux. Doing so avoids the need to revise queries changing column names, deleting unused columns and adding new columns or ones that were forgotten. Once stable and before an application is released and finally tested, a code review should tidy up the queries.

    Nick

  2. true nick. sometimes * will be much faster like here. Small smaple shows index can be used for count and data does not have to be touched at all.

    mysql> explain select timestamp,count(*) from log_entry where timestamp = 2454944;
    +—-+————-+———–+——+—————+———–+———+——-+———+————————–+
    | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
    +—-+————-+———–+——+—————+———–+———+——-+———+————————–+
    | 1 | SIMPLE | log_entry | ref | multi_one | multi_one | 5 | const | 1616103 | Using where; Using index |
    +—-+————-+———–+——+—————+———–+———+——-+———+————————–+
    1 row in set (0.00 sec)

    mysql> explain select timestamp,count(id) from log_entry where timestamp = 2454944;
    +—-+————-+———–+——+—————+———–+———+——-+———+————-+
    | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
    +—-+————-+———–+——+—————+———–+———+——-+———+————-+
    | 1 | SIMPLE | log_entry | ref | multi_one | multi_one | 5 | const | 1616103 | Using where |
    +—-+————-+———–+——+—————+———–+———+——-+———+————-+
    1 row in set (0.00 sec)

  3. I just ran a simple check to test and can confirm. Selecting count(*) and count(id) (id is a key) yields about the same results. Selecting count(name) where `name` is non-indexed if far slower.

    Also note that selecting count(fieldname) doesn’t necessarily yield the number of rows in the table- just the number where fieldname is not null. So, naturally there’s some additional data-evaluating going on.

    (root@localhost:test) desc big;
    +——-+——————+——+—–+———+—————-+
    | Field | Type | Null | Key | Default | Extra |
    +——-+——————+——+—–+———+—————-+
    | id | int(11) unsigned | NO | PRI | NULL | auto_increment |
    | name | varchar(255) | YES | | NULL | |
    +——-+——————+——+—–+———+—————-+

    (root@localhost:test) select count(*) from big;
    +———-+
    | count(*) |
    +———-+
    | 10645312 |
    +———-+
    1 row in set (0.00 sec)

    (root@localhost:test) select count(id) from big;
    +———–+
    | count(id) |
    +———–+
    | 10645312 |
    +———–+
    1 row in set (0.00 sec)

    (root@localhost:test) select count(name) from big;
    +————-+
    | count(name) |
    +————-+
    | 10645312 |
    +————-+
    1 row in set (4.29 sec)

    (root@localhost:test) update big set name=NULL where name > ‘z’;
    Query OK, 304167 rows affected (32.82 sec)
    Rows matched: 304167 Changed: 304167 Warnings: 0

    (root@localhost:test) select count(name) from big;
    +————-+
    | count(name) |
    +————-+
    | 10341145 |
    +————-+
    1 row in set (4.27 sec)

User contributed tags for this post:

mysql join performance (398) - mysql count performance (206) - mysql union performance (162) - mysql count speed (139) - mysql performance tips (139) - mysql count slow (133) - mysql count(*) slow (71) - mysql performance join (64) - mysql multicore (63) - mysql joins performance (57) - mysql join large tables (57) - mysql count(*) performance (42) - mysql union slow (42) - mysql performance count (37) - mysql large joins (36) - wordpress mysql performance (35) - mysql union speed (33) - mysql join performance tips (31) - mysql count optimization (28) - mysql multi core (26) - mysql join big tables (25) - mysql join slow (25) - count(*) performance mysql (25) - mysql performance joins (24) - mysql optimize count (24) - MySQL large join (22) - mysql count(*) optimization (22) - mysql performance union (21) - mysql join large table (21) - mysql join speed (20) - mysql performance large tables (20) - mysql where count(*) (20) - mysql large table performance (19) - mysql large tables performance (18) - count mysql performance (17) - easy mysql (16) - mysql count optimize (15) - mysql large table joins (15) - mysql performance (14) - wordpress mysql slow (14) - performance join mysql (14) - join large tables mysql (14) - mysql joining large tables (14) - mysql slow union (14) - COUNT(*) slow mysql (13) - where count(*) mysql (13) - mysql multicore performance (13) - mysql large table join (12) - mysql optimize count(*) (12) - mysql join count slow (12) - join performance mysql (11) - optimize mysql count (11) - mysql join tips (11) - optimize count(*) mysql (11) - mysql speed tips (11) - join mysql performance (11) - mysql count(*) optimize (11) - mysql where in performance (11) - mysql performance count(*) (11) - mysql performance big tables (10) - mysql slow join (10) - mysql multi core performance (10) - count(*) speed mysql (10) - mysql big tables (9) - mysql performance wordpress (9) - mysql join optimization (9) - mysql multi core optimization (9) - mysql multi-core (9) - mysql where COUNT(*) > 1 (9) - mysql count(*) > 1 (9) - mysql select count performance (9) - mysql query optimization tips (8) - union mysql performance (8) - mysql count union (8) - count(*) count(1) mysql (8) - mysql count(1) (8) - mysql joins on large tables (8) - mysql speed up count (8) - mysql (7) - mysql big tables performance (7) - JOINs performance IN MYSQL (7) - mysql large table slow (7) - mysql join table performance (7) - mysql join huge tables (7) - optimize mysql union (7) - mysql speed up union (7) - mysql optimize join large tables (7) - mysql slow large tables (7) - mysql speed up join (7) - mysql join count(*) (7) - easymysql (7) - mysql slow count (7) - mysql 4 multicore (7) - mysql join table speed (6) - count(1) mysql (6) - optimize mysql multicore (6) - mysql join large table performance (6) - mysql where 1=1 (6) - mysql huge (6) - mysql huge joins (6) - mysql speed (6) - mysql multiple join performance (6) - optimize mysql count(*) (6) - performance mysql join (6) - mysql join two big tables (6) - mysql speed count (6) - mysql select count slow (6) - mysql left join performance (6) - mysql large tables tips (6) - cache 63CG UrCLvcJ maisonbisson com blog post 11102 fee (5) - mysql performance on large tables (5) - mysql join where performance (5) - count(*) mysql optimisation (5) - mysql count join (5) - mysql union optimization (5) - mysql optimizar count(*) (5) - mysql performance join where (5) - mysql performance large table (5) - count speed mysql (5) - mysql joining two large tables (5) - COUNT(*) MYSQL JOIN (5) - mysql performance many columns (5) - mysql performance where 1=1 (5) - mysql speed up joins (5) - mysql union large tables (5) - mysql select count speed (5) - mysql count large table slow (4) - mysql join tables performance (4) - mysql preformance (4) - mysql big table performance (4) - mysql join count (4) - mysql optimization tips (4) - mysql speedup (4) - mysql performance join large tables (4) - mysql huge join (4) - mysql count star (4) - mysql count optomise (4) - MYSQL QUERY PERFORMANCE (4) - mysql speedup count (4) - optimizing mysql count(*) (4) - MySQL where count (4) - mysql large performance (4) - mysql count(*)>1 (4) - mysql count join performance (4) - mysql COUNT() speed (4) - large table join mysql (4) - join large table mysql (4) - mysql optimizing count (4) - mysql optimization count(*) (4) -