【问题标题】:MariaDB index for queries of a subset of column1 and range of column2MariaDB 索引,用于查询 column1 的子集和 column2 的范围
【发布时间】:2023-03-27 13:06:01
【问题描述】:

我有这个问题:

SELECT column1 FROM table WHERE column2 IN (*small set of values*) AND column3 > number

我的表有3列,主键是(column1,column2)。

所以我正在研究复合索引,但我不太清楚索引中的列应该按什么顺序排列(column2,column3)或(column3,column2),因为没有太多关于 BTree 的确切信息建立这个复合索引(至少我无法理解)。

那么,树是如何构建的,它对我的​​帮助不仅仅是为 column2 创建和索引吗?

额外问题:我在这里看到了一些关于“覆盖”索引的东西,这似乎对我有用,但是看到没有“免费餐”,这意味着什么?更少的索引适合内存? MariaDB 甚至会将索引存储在内存中吗?

【问题讨论】:

    标签: mysql mariadb database-indexes


    【解决方案1】:

    (我假设您使用的是 InnoDB。)

    • 如果IN> 更具选择性,INDEX(col2, ...) 会更好。
    • 如果> 更有选择性,INDEX(col3, ...) 会更好。
    • InnoDB 总是将PRIMARY KEY 列放在每个二级索引的末尾。因此,INDEX(col2, col3) 非常像INDEX(col2, col3, col1),即“覆盖”。 (col3, col2) 同上。
    • 当期望添加 PK 时,我明确添加了它 - 这是其他用户(和我自己)的线索,我正在努力实现“覆盖”或其他目的。
    • 优化器(参见“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 的其他用途。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-13
      • 2015-07-31
      • 2011-01-29
      • 2018-02-20
      • 2018-05-27
      • 2013-01-02
      • 1970-01-01
      相关资源
      最近更新 更多