我有个问题: SELECT column1 FROM table WHERE column2 IN (*small set of values*) AND column3 > number
我的表有3列,主键是(column1,column2)。
所以我研究了复合索引,但是我不太清楚索引中的列应该是(column2,column3)还是(column3,column2)的顺序,因为没有太多关于这个复合索引的btree究竟是如何构建的信息(至少我不明白)。
那么,树是如何构建的,它比只为column2创建和索引更有帮助吗?
额外的问题:我看到了一些关于“覆盖”指数的东西,这似乎对我很有用,但鉴于没有“免费膳食”,这意味着什么?更少的索引适合内存?mariadb是否将索引存储在内存中?
1条答案
按热度按时间kmynzznz1#
(我假设您使用的是innodb。)
INDEX(col2, ...)
如果IN
它比>
.INDEX(col3, ...)
如果>
更具选择性。innodb总是把
PRIMARY KEY
列放在每个次索引的末尾。因此,INDEX(col2, col3)
非常像INDEX(col2, col3, col1)
,即“覆盖”。同上(col3, col2)
.当我希望添加pk时,我显式地添加了它——这给其他用户(和我自己)提供了一个线索,告诉他们我正在努力“覆盖”或其他什么。
优化器(cf“mrr”)可能能够跨越
IN
价值观,所以。。。我特别建议:
最好改成
PRIMARY KEY(col2, col1)
没有额外的索引。这假设您没有col1
首先在pk中使用其他查询。复合索引是如何在btree中完成的?可以考虑将列(col1,col2)连接在一起,形成一个键(细节可能更混乱,但这样想“管用”。)
进一步说明:数据是数据的一个btree,根据pk排序。次索引是次索引中列的btree加上pk,在叶节点中没有额外的内容。
mysql和mariadb将所有索引存储在磁盘上(见上文),然后将16kb块缓存在ram中的“buffer\u pool”中。系统运行一段时间后,索引块往往会在该缓存中;数据块可以是也可以不是。
如果您只在一个大的、面向时间的表中查看“新”行,那么按日期或时间索引的块
AUTO_INCREMENT
id将倾向于在ram中,而“较旧”的行则留在磁盘上。这就是“缓存”的美妙之处——比起笨拙的技术,你更接近“免费一餐”。例如……”我将把我所有的索引加载到ram中。”但是如果我只使用它的‘更新’部分怎么办;这将排除ram的其他用途。”我将把这个表锁在ram中。”再次强调,这窃取了ram的其他用途,可能更有效。