我正在执行一个简单的选择查询来从表日志中提取用户名(包含54864行)。 检索数据花了大约7.836秒。 我怎样才能加快效果?
SELECT username FROM `logs`
WHERE
logs.branch=1
and
logs.added_on > '2016-11-27 00:00:00'
在描述表格时,
+-------------------+-------------+------+-----+---------+----------------+
| 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
解释查询,
+----+-------------+--------------------------+------+-----------------------------+--------------+---------+-------+------+-------------+
| 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
更新::在添加复合索引(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 :(得分:2)
在branch,added_on
上添加一个复合键,因此您可以覆盖所有WHERE条件,因为您使用了AND。
ALTER TABLE logs ADD KEY(branch,added_on)
这应该快得多,你也可以删除branch_index
键,因为上面的索引可以替换它。你只能从54000返回37行,所以基数没问题。
ALTER TABLE logs DROP INDEX `branch_index`;
或者您可以使用索引提示
SELECT username FROM `logs` USE INDEX (branch_added_index) WHERE
logs.branch=1
and
logs.added_on > '2016-11-27 00:00:00'
答案 1 :(得分:2)
如果您的表的现有索引已用于其他查询,请尝试添加如下所示的新复合索引
create index <indexname> on logs(branch,added_on)
答案 2 :(得分:1)
在2个字段(branch,added_on)上创建一个复合索引,如:
ALTER TABLE `logs` ADD KEY idx_branch_added (branch, added_on);
答案 3 :(得分:1)
这会更快,因为它是“覆盖”:
INDEX(branch, added_on, username) -- in exactly that order.
(并删除任何作为前缀的索引。)
“基数”很少有重要性。并且EXPLAIN
经常会出现错误的价值。
EXPLAIN
显示5
branch
的大小 - 是否真的需要NULLable
?你会有20亿支?考虑使用更小的东西,例如1字节TINYINT UNSIGNED NOT NULL
(值0..255)。
另外,将255
缩小到合理的范围。
在描述表格时,请使用SHOW CREATE TABLE
;它更具描述性。了解引擎,Charset等可能会有所帮助。