如何在没有MySQL客户端的情况下直接访问MySQL InnoDB索引值?

jmi*_*loy 10 c mysql indexing innodb

a VARCHAR(255), b INT在InnoDB表中有一个列索引.给定两a,b对,我可以使用MySQL索引来确定ac程序中的对是否相同(即不使用strcmp和数字比较)?

  1. 存储在文件系统中的MySQL InnoDB索引在哪里?
  2. 可以从单独的程序中读取和使用吗?格式是什么?
  3. 如何使用索引来确定两个键是否相同?

注意:这个问题的答案应该是:a)提供一种访问MySQL索引的方法以完成这项任务,或者b)解释为什么不能以这种方式实际访问/使用MySQL索引.特定于平台的答案很好,我在使用Red Hat 5.8.


下面是这个问题的先前版本,它提供了更多的背景,但似乎分散了实际问题的注意力.我知道在MySQL中有其他方法可以完成这个例子,我提供了两个.这不是关于优化的问题,而是分解出许多不同动态生成的查询中存在的复杂性.

我可以使用子分组的子选择来完成我的查询,例如

SELECT c, AVG(max_val)
FROM (
    SELECT c, MAX(val) AS max_val
    FROM table
    GROUP BY a, b) AS t
GROUP BY c
Run Code Online (Sandbox Code Playgroud)

但我写了一个UDF,允许我用一个选择来做,例如

SELECT b, MY_UDF(a, b, val)
FROM table
GROUP by c
Run Code Online (Sandbox Code Playgroud)

这里的关键是,我穿过田野ab对UDF,和我手动管理a,b各组群.列a是一个varchar,所以这涉及strncmp到检查匹配的调用,但速度相当快.

但是,我有一个索引my_key (a ASC, b ASC).而不是手动检查a和b上的匹配,我可以访问并使用MySQL索引吗?也就是说,我可以在my_key中获取a,bc中给定行或对的索引值(在UDF内)吗?如果是这样,指数值是否会保证对任何值都是唯一的a,b

我想调用MY_UDF(a, b, val)然后(a,b)从UDF中查找c中的mysql索引值.

Rol*_*DBA 6

回顾一下您的原始查询

SELECT c, AVG(max_val)
FROM
(
    SELECT c, MAX(val) AS max_val
    FROM table
    GROUP BY a, b
) AS t
GROUP BY c;
Run Code Online (Sandbox Code Playgroud)

您应首先确保子选择通过运行为您提供所需的内容

SELECT c, MAX(val) AS max_val
FROM table
GROUP BY a, b;
Run Code Online (Sandbox Code Playgroud)

如果subselect的结果正确,则运行完整查询.如果结果正确,那么您应该执行以下操作:

ALTER TABLE `table` ADD INDEX abc_ndx (a,b,c,val);
Run Code Online (Sandbox Code Playgroud)

这将通过仅从索引获取所有需要的数据来加速查询.源表永远不需要咨询.

编写UDF并将其称为单个SELECT只是伪装一个子选择并创建比查询需要更多的开销.只需在存储过程中放置​​完整查询(对数据进行一次嵌套传递)就可以更有效地获取UDF中的大部分数据并迭代地执行单行选择(类似于O(n log n)运行时间可能更长)Sending data状态).

更新2012-11-27 13:46美国东部时间

您可以通过执行两项操作来访问索引而无需触及表

  • 创建一个体面的覆盖指数

    ALTER TABLE tableADD INDEX abc_ndx(a,b,c,val);

  • 运行SELECT我之前提到的查询

由于查询的所有列都在索引中,因此查询优化器将仅触摸索引(或预缓存索引页).如果表是MyISAM,你可以......

  1. 将MyISAM表设置为具有可在mysqld启动时预加载的专用密钥缓存
  2. 运行SELECT a,b,c,val FROM table;以将索引页加载到MyISAM的默认密钥缓存中

相信我,你真的不想访问mysqld遗嘱的索引页面.那是什么意思?

对于MyISAM,MyISAM表的索引页存储在表的.MYI文件中.每个DML语句将召唤一个完整的表锁.

对于InnoDB,索引页面被加载到InnoDB缓冲池中.因此,关联的数据页面也将加载到InnoDB缓冲池中.

您不必使用Python,Perl,PHP,C++或Java来规避对索引页的访问,因为MyISAM需要不断的I/O或InnoDB执行的常量MVCC协议.

有一个NoSQL范例(称为HandlerSocket)允许对MySQL表的低级访问,可以干净地绕过mysqld的正常访问模式.我不推荐它,因为在使用它来发出写入时有一个错误.

更新2012-11-30 12:11美国东部时间

从你上次的评论

我正在使用InnoDB,我可以看到MVCC模型如何使事情复杂化.但是,显然InnoDB只在索引中存储了一个版本(最新版本).相关表的访问模式是一次写入,多次读取,因此如果可以访问索引,则可以为每个键提供单个可靠的数据.

说到InnoDB,MVCC并没有让任何事情变得复杂.它实际上可以成为你最好的朋友提供:

  • 如果您启用了自动提交(默认情况下应该启用)
  • 相关表的访问模式是一次写入,多次读取

如果重复读取,我希望所访问的索引页几乎永远位于InnoDB缓冲池中.我只想确保你的innodb_buffer_pool_size设置得足够高,以保存必要的InnoDB数据.


Ale*_*x I 4

如果您只想访问 MySQL 之外的索引,则必须使用MySQL 存储引擎之一的 API 。默认引擎是InnoDB。请参阅此处的概述:InnoDB 内部结构。它(在非常高的层面上)描述了磁盘上的数据布局以及访问它的 API。更详细的描述在这里:Embedded InnoDB

但是,您可以使用已经完成该工作的项目之一,而不是直接编写自己的使用 InnoDB API 的程序(这需要大量工作):

  • HandlerSocket:提供对 InnoDB 表的 NoSQL 访问,在 UDF 中运行。请参阅开发人员发布的内容非常丰富的博客文章。HandlerSocket 的目标是提供一个作为网络守护进程公开的 NoSQL 接口,但您可以使用相同的技术(以及大部分相同的代码)来提供 MySQL 查询将使用的内容。

  • memcached InnoDB 插件。提供对 InnoDB 表的 memcached 样式访问。

  • HailDB:提供对 InnoDB 表的 NoSQL 访问,在嵌入式 InnoDB 之上运行。参见会议演讲编辑: HailDB 可能无法与 MySQL 并行运行。

我相信其中任何一个都可以与 MySQL 并行运行(使用相同的实时表),并且可以从 C 语言使用,因此它们确实满足您的要求。

如果您可以使用/迁移到 MySQL Cluster,另请参阅 NDB API(直接 API)和ndbmemcache(一种使用 memcache API 访问 MySQL Cluster 的方法)。

如果不知道为什么要尝试这样做,则很难回答这个问题,因为不同方法的含义非常不同。