3

I am performing a simple select query to extract username from table logs(containing 54864 rows). It took about 7.836s to retrieve data. How can I speed up the performace???

SELECT username FROM `logs`
WHERE 
logs.branch=1 
and
logs.added_on > '2016-11-27 00:00:00'

On describing table,

+-------------------+-------------+------+-----+---------+----------------+
| Field             | Type        | Null | Key | Default | Extra          |
+-------------------+-------------+------+-----+---------+----------------+
| id                | int(11)     | NO   | PRI | NULL    | auto_increment |
| username          | char(255)   | YES  | MUL | NULL    |                |
| fullname          | char(255)   | YES  |     | NULL    |                |
| package           | char(255)   | YES  |     | NULL    |                |
| prev_expiry       | date        | YES  |     | NULL    |                |
| recharged_upto    | date        | YES  |     | NULL    |                |
| payment_option    | int(11)     | YES  | MUL | NULL    |                |
| amount            | float(14,2) | YES  |     | NULL    |                |
| branch            | int(11)     | YES  | MUL | NULL    |                |
| added_by          | int(11)     | YES  |     | NULL    |                |
| added_on          | datetime    | YES  | MUL | NULL    |                |
| remark            | text        | YES  |     | NULL    |                |
| payment_mode      | char(255)   | YES  |     | NULL    |                |
| recharge_duration | char(255)   | YES  |     | NULL    |                |
| invoice_number    | char(255)   | YES  |     | NULL    |                |
| cheque_no         | char(255)   | YES  |     | NULL    |                |
| bank_name         | char(255)   | YES  |     | NULL    |                |
| verify_by_ac      | int(11)     | YES  |     | 0       |                |
| adjusted_days     | int(11)     | YES  |     | NULL    |                |
| adjustment_note   | text        | YES  |     | NULL    |                |
+-------------------+-------------+------+-----+---------+----------------+
20 rows in set

On explaining query,

+----+-------------+--------------------------+------+-----------------------------+--------------+---------+-------+------+-------------+
| id | select_type | table                    | type | possible_keys               | key          | key_len | ref   | rows | Extra       |
+----+-------------+--------------------------+------+-----------------------------+--------------+---------+-------+------+-------------+
|  1 | SIMPLE      | logs                     | ref  | branch_index,added_on_index | branch_index | 5       | const |   37 | Using where |
+----+-------------+--------------------------+------+-----------------------------+--------------+---------+-------+------+-------------+
1 row in set

updated:: explaing query after adding composite index(branch_added_index )

+----+-------------+--------------------------+------+------------------------------------------------+--------------+---------+-------+------+-------------+
| id | select_type | table                    | type | possible_keys                                  | key          | key_len | ref   | rows | Extra       |
+----+-------------+--------------------------+------+------------------------------------------------+--------------+---------+-------+------+-------------+
|  1 | SIMPLE      | logs                     | ref  | branch_index,added_on_index,branch_added_index | branch_index | 5       | const |   37 | Using where |
+----+-------------+--------------------------+------+------------------------------------------------+--------------+---------+-------+------+-------------+
1 row in set
0

4 Answers 4

2

Add a composite key on branch,added_on so you cover all the WHERE conditions since you use AND.

ALTER TABLE logs ADD KEY(branch,added_on)

This should be much faster,also you can drop the branch_index key since the above index can replace it.You only return 37 rows from 54000 so the cardinality is OK.

ALTER TABLE logs DROP INDEX `branch_index`;

Or you can use index hints

SELECT username FROM `logs` USE INDEX (branch_added_index)  WHERE 
logs.branch=1 
and
logs.added_on > '2016-11-27 00:00:00'
Sign up to request clarification or add additional context in comments.

5 Comments

I have created the composite index as you suggested but still query execution time is not improved
@kamalrumba Add the new explain and drop the old index
@kamalrumba From the new explain I see the query still uses the old index.Just drop it
I have dropped the index as you suggested and query execution time improved considerably. Can you please explain why separately created indexes on the same column is slower then the composited index.
@kamalrumba In short, the new index has better cardinality, it can take into account both conditions at the same time while the old index selected all logs.branch=1 and after that it scanned the other column.
2

if your table's existing index is already used for other queries try adding new composite index like below create index <indexname> on logs(branch,added_on)

1 Comment

I think we've got the message
1

create a composite index on 2 fields (branch, added_on) like:

ALTER TABLE `logs` ADD KEY idx_branch_added (branch, added_on);

Comments

1

This will be even faster, because it is "covering":

INDEX(branch, added_on, username) -- in exactly that order.

(And drop any indexes that are prefixes of this.)

Index Cookbook

"Cardinality" is rarely of importance. And EXPLAIN often gets the value wrong.

The EXPLAIN shows 5 for the size of branch -- does it really need to be NULLable? Will you have 2 billion branches? Consider using something smaller, such as the 1-byte TINYINT UNSIGNED NOT NULL (values 0..255).

Also, shrink the 255 to something reasonable.

When describing a table, please use SHOW CREATE TABLE; it is more descriptive. It might help to know the Engine, Charset, etc.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.