【发布时间】:2019-06-24 02:25:58
【问题描述】:
我有一个 Providers 表,如下所示:
|编号 |姓氏 |名字 |中间名 | | --- | -------- | --------- | ---------- |具有以下索引:
- Providers_lastName
- Providers_firstName
- Providers_lastName_firstName
- Providers_lastName_firstName_middleName
我的所有查询在 lastName 和 firstName 值中都使用尾随通配符:
SELECT * FROM Providers
WHERE lastName LIKE 'smi%'
ORDER BY lastName ASC, firstName ASC, middleName
LIMIT 0, 50
SELECT * FROM Providers
WHERE firstName LIKE 'mar%'
ORDER BY lastName ASC, firstName ASC, middleName
LIMIT 0, 50
我在这个表中有大约 700 万行。我的姓氏查询非常快。但是,firstName 的速度非常慢。我在这里做错了什么吗?在不更改或删除顺序的情况下,我还可以添加哪些其他索引来提高仅 firstName 查询的性能?
编辑 1:
EXPLAINlastName 查询的输出:
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "69901.30"
},
"ordering_operation": {
"using_filesort": false,
"table": {
"table_name": "Providers",
"access_type": "range",
"possible_keys": [
"Providers_lastName",
"Providers_lastName_firstName",
"Providers_lastName_firstName_middleName"
],
"key": "Providers_lastName_firstName_middleName",
"used_key_parts": [
"lastName"
],
"key_length": "143",
"rows_examined_per_scan": 59008,
"rows_produced_per_join": 59008,
"filtered": "100.00",
"index_condition": "(`db_name`.`providers`.`lastName` like 'smi%')",
"cost_info": {
"read_cost": "64000.51",
"eval_cost": "5900.80",
"prefix_cost": "69901.31",
"data_read_per_join": "158M"
},
"used_columns": [
"id",
"firstName",
"middleName",
"lastName",
// OTHER COLUMNS
]
}
}
}
}
EXPLAINfirstName 查询的输出:
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "390813.95"
},
"ordering_operation": {
"using_filesort": false,
"table": {
"table_name": "Providers",
"access_type": "index",
"possible_keys": [
"Providers_firstName"
],
"key": "Providers_lastName_firstName_middleName",
"used_key_parts": [
"lastName",
"firstName",
"middleName"
],
"key_length": "309",
"rows_examined_per_scan": 948,
"rows_produced_per_join": 329914,
"filtered": "5.27",
"cost_info": {
"read_cost": "357822.55",
"eval_cost": "32991.40",
"prefix_cost": "390813.95",
"data_read_per_join": "883M"
},
"used_columns": [
"id",
"firstName",
"middleName",
"lastName",
// OTHER COLUMNS
],
"attached_condition": "(`db_name`.`providers`.`firstName` like 'mar%')"
}
}
}
}
SHOW CREATE TABLE:
CREATE TABLE `Providers` (
`id` varchar(10) NOT NULL,
`firstName` varchar(20) DEFAULT NULL,
`middleName` varchar(20) DEFAULT NULL,
`lastName` varchar(35) DEFAULT NULL,
/* Other columns */
PRIMARY KEY (`id`),
KEY `Providers_firstName` (`firstName`),
KEY `Providers_lastName` (`lastName`),
KEY `Providers_lastName_firstName` (`lastName`,`firstName`),
KEY `Providers_lastName_firstName_middleName` (`lastName`,`firstName`,`middleName`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
编辑 2:
运行FLUSH STATUS 后SHOW SESSION STATUS LIKE 'Handler%' 的输出:
查询 1(名字):
{
"data":
[
{
"Variable_name": "Handler_commit",
"Value": "1"
},
{
"Variable_name": "Handler_delete",
"Value": "0"
},
{
"Variable_name": "Handler_discover",
"Value": "0"
},
{
"Variable_name": "Handler_external_lock",
"Value": "2"
},
{
"Variable_name": "Handler_mrr_init",
"Value": "0"
},
{
"Variable_name": "Handler_prepare",
"Value": "0"
},
{
"Variable_name": "Handler_read_first",
"Value": "1"
},
{
"Variable_name": "Handler_read_key",
"Value": "1"
},
{
"Variable_name": "Handler_read_last",
"Value": "0"
},
{
"Variable_name": "Handler_read_next",
"Value": "1487176"
},
{
"Variable_name": "Handler_read_prev",
"Value": "0"
},
{
"Variable_name": "Handler_read_rnd",
"Value": "0"
},
{
"Variable_name": "Handler_read_rnd_next",
"Value": "0"
},
{
"Variable_name": "Handler_rollback",
"Value": "0"
},
{
"Variable_name": "Handler_savepoint",
"Value": "0"
},
{
"Variable_name": "Handler_savepoint_rollback",
"Value": "0"
},
{
"Variable_name": "Handler_update",
"Value": "0"
},
{
"Variable_name": "Handler_write",
"Value": "0"
}
]
}
查询 2(姓氏):
{
"data":
[
{
"Variable_name": "Handler_commit",
"Value": "1"
},
{
"Variable_name": "Handler_delete",
"Value": "0"
},
{
"Variable_name": "Handler_discover",
"Value": "0"
},
{
"Variable_name": "Handler_external_lock",
"Value": "2"
},
{
"Variable_name": "Handler_mrr_init",
"Value": "0"
},
{
"Variable_name": "Handler_prepare",
"Value": "0"
},
{
"Variable_name": "Handler_read_first",
"Value": "0"
},
{
"Variable_name": "Handler_read_key",
"Value": "1"
},
{
"Variable_name": "Handler_read_last",
"Value": "0"
},
{
"Variable_name": "Handler_read_next",
"Value": "49"
},
{
"Variable_name": "Handler_read_prev",
"Value": "0"
},
{
"Variable_name": "Handler_read_rnd",
"Value": "0"
},
{
"Variable_name": "Handler_read_rnd_next",
"Value": "0"
},
{
"Variable_name": "Handler_rollback",
"Value": "0"
},
{
"Variable_name": "Handler_savepoint",
"Value": "0"
},
{
"Variable_name": "Handler_savepoint_rollback",
"Value": "0"
},
{
"Variable_name": "Handler_update",
"Value": "0"
},
{
"Variable_name": "Handler_write",
"Value": "0"
}
]
}
编辑 3
使用FORCE_INDEX(Providers_firstName):
EXPLAINfirstName 查询的输出:
{
"query_block": {
"select_id": 1,
"cost_info": {
"query_cost": "389514.60"
},
"ordering_operation": {
"using_filesort": true,
"table": {
"table_name": "Providers",
"access_type": "range",
"possible_keys": [
"Providers_firstName"
],
"key": "Providers_firstName",
"used_key_parts": [
"firstName"
],
"key_length": "83",
"rows_examined_per_scan": 329914,
"rows_produced_per_join": 329914,
"filtered": "100.00",
"index_condition": "(`db_name`.`providers`.`firstName` like 'mar%')",
"cost_info": {
"read_cost": "356523.20",
"eval_cost": "32991.40",
"prefix_cost": "389514.60",
"data_read_per_join": "883M"
},
"used_columns": [
"id",
"firstName",
"middleName",
"lastName",
// Other columns
]
}
}
}
}
处理程序计数:
{
"data":
[
{
"Variable_name": "Handler_commit",
"Value": "1"
},
{
"Variable_name": "Handler_delete",
"Value": "0"
},
{
"Variable_name": "Handler_discover",
"Value": "0"
},
{
"Variable_name": "Handler_external_lock",
"Value": "2"
},
{
"Variable_name": "Handler_mrr_init",
"Value": "0"
},
{
"Variable_name": "Handler_prepare",
"Value": "0"
},
{
"Variable_name": "Handler_read_first",
"Value": "0"
},
{
"Variable_name": "Handler_read_key",
"Value": "51"
},
{
"Variable_name": "Handler_read_last",
"Value": "0"
},
{
"Variable_name": "Handler_read_next",
"Value": "168497"
},
{
"Variable_name": "Handler_read_prev",
"Value": "0"
},
{
"Variable_name": "Handler_read_rnd",
"Value": "50"
},
{
"Variable_name": "Handler_read_rnd_next",
"Value": "0"
},
{
"Variable_name": "Handler_rollback",
"Value": "0"
},
{
"Variable_name": "Handler_savepoint",
"Value": "0"
},
{
"Variable_name": "Handler_savepoint_rollback",
"Value": "0"
},
{
"Variable_name": "Handler_update",
"Value": "0"
},
{
"Variable_name": "Handler_write",
"Value": "0"
}
]
}
【问题讨论】:
-
好奇每个查询的总记录数是多少? (您的样本中的那些,您的退货限制为 50,但两种情况下的行数是多少)
-
我怀疑 order by 是您的问题。可能会发生表扫描,因为第一个 order by 字段不是您为 fname 查询过滤的 col。尝试将您的记录选择到临时表中,然后从中选择 * order by。
-
@IlanP,
firstName查询的总记录数为 168,497,我第一次运行它大约需要 20 秒。另一个的计数要少得多(30、298),但即使提取更多记录也更有效。例如,检索所有 lastName 以s开头的记录 (456,194) 只需要 1.5 毫秒。 -
请提供
SHOW CREATE TABLE和EXPLAIN SELECT...