【发布时间】:2011-01-04 02:27:25
【问题描述】:
一位同事让我解释索引(指数?)如何提高性能;我试图这样做,但我自己也很困惑。
我使用下面的模型进行解释(错误/诊断日志数据库)。它由三个表组成:
- 业务系统列表,包含其名称的“系统”表
- 不同类型的跟踪列表,表“TraceTypes”,定义可以记录哪些类型的错误消息
- 实际跟踪消息,具有来自
System和TraceTypes表的外键
我在演示中使用了 MySQL,但是我不记得我使用的表类型。我认为是 InnoDB。
System TraceTypes
----------------------------- ------------------------------------------
| ID | Name | | ID | Code | Description |
----------------------------- ------------------------------------------
| 1 | billing | | 1 | Info | Informational mesage |
| 2 | hr | | 2 | Warning| Warning only |
----------------------------- | 3 | Error | Failure |
| ------------------------------------------
| ------------|
Traces | |
--------------------------------------------------
| ID | System_ID | TraceTypes_ID | Message |
--------------------------------------------------
| 1 | 1 | 1 | Job starting |
| 2 | 1 | 3 | System.nullr..|
--------------------------------------------------
首先,我向所有表中添加了一些记录,并证明下面的查询在 0.005 秒内执行:
select count(*) from Traces
inner join System on Traces.System_ID = System.ID
inner join TraceTypes on Traces.TraceTypes_ID = TraceTypes.ID
where
System.Name='billing' and TraceTypes.Code = 'Info'
然后我生成了更多数据(还没有索引)
- “系统”包含大约 100 个条目
- “TraceTypes”包含大约 50 个条目
- “跟踪”包含约 1000 万条记录。
现在之前的查询需要 8-10 秒。
我在Traces.System_ID 列和Traces.TraceTypes_ID 列上创建了索引。现在这个查询在毫秒内执行:
select count(*) from Traces where System_id=1 and TraceTypes_ID=1;
这也很快:
select count(*) from Traces
inner join System on Traces.System_ID = System.ID
where System.Name='billing' and TraceTypes_ID=1;
但之前连接所有三个表的查询仍然需要 8-10 秒才能完成。
仅当我创建复合索引(索引中包含 System_ID 和 TraceTypes_ID 列)时,速度才下降到毫秒。
我之前学到的基本语句是“您用于连接的所有列都必须被索引”。
然而,在我的场景中,我在System_ID 和TraceTypes_ID 上都有索引,但是 MySQL 没有使用它们。问题是——为什么?我的赌注是 - 项目计数比率 100:10,000,000:50 会使单列索引太大而无法使用。但这是真的吗?
【问题讨论】:
标签: mysql performance join indexing