Reputation: 700
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
Upvotes: 3
Views: 1140
Reputation: 142278
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.)
"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.
Upvotes: 1
Reputation: 26784
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'
Upvotes: 2
Reputation: 3274
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)
Upvotes: 2
Reputation: 15057
create a composite index on 2 fields (branch, added_on) like:
ALTER TABLE `logs` ADD KEY idx_branch_added (branch, added_on);
Upvotes: 1