我有这个查询:
SELECT column1 FROM table WHERE column2 IN (*small set of values*) AND column3 > number
我的表有3列,主键为(column1,column2(。
所以我在研究复合索引,但我不太清楚索引中的列应该是什么顺序(column2,column3(或(column3,column2(,因为没有太多关于如何构建该复合索引的BTree的信息(至少我不明白(。
那么,这个树是如何构建的呢?它会比只为第2列创建和索引更帮助我吗?
额外的问题:我在这里看到了一些关于"覆盖"指数的内容,这似乎对我有用,但鉴于没有"免费用餐",这意味着什么?更少的索引适合记忆?MariaDB是否将索引存储在内存中?
(我假设您使用的是InnoDB。(
如果IN
比>
更具选择性,则INDEX(col2, ...)
将更好- 如果CCD_ 6的选择性更强,则CCD_
- InnoDB总是将
PRIMARY KEY
列放在每个辅助索引的末尾。因此,INDEX(col2, col3)
非常像INDEX(col2, col3, col1)
,它是"覆盖"的。(col3, col2)
同上 - 当期望添加PK时,我明确地添加了它——这向其他用户(和我自己(提供了一条线索,告诉他们我正在努力"覆盖"或其他什么
- 优化器(cf"MRR"(可能能够跨越
IN
值,因此
我特别推荐:
INDEX(col2, -- hoping to leapfrog
col3, -- assuming the leapfrogging works
col1) -- covering
可能最好改为PRIMARY KEY(col2, col1)
,而没有的额外索引。此假设您在PK中没有首先使用col1
,从而有利于其他一些查询。
BTree中的合成索引是如何完成的?考虑将列(col1,col2(连接在一起以形成单个键。(细节可能更混乱,但这样想是"可行的"。(
进一步注意:Data是数据的BTree,根据PK排序。辅助索引是辅助索引中列的BTree加上PK,叶节点中没有任何额外内容。
MySQL和MariaDB将所有索引存储在磁盘上(见上文(,然后将16KB的块缓存在RAM中的"buffer_pool"中。系统运行一段时间后,索引块往往在该缓存中;数据块可以是也可以不是。
如果您只在一个面向时间的大表中查看"新"行,那么由日期或AUTO_INCREMENT
id索引的块将倾向于在ram中,而"旧"行则保留在磁盘上。
这就是"缓存"的美妙之处——比起笨拙的技术,你更接近于"免费用餐"。比如…"我会把我所有的索引都加载到RAM中。"但如果我只使用它的"更新"部分呢;这将排挤RAM的其他用途。"我会把这个表锁在RAM里。"同样,这会从其他可能更有效的RAM用途中窃取信息。