10

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

  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

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

SELECT b, MY_UDF(a, b, val)
FROM table
GROUP by c

这里的关键是我将字段传递给 UDF,并且我手动管理a每个组中的子组。Column是一个 varchar,所以这涉及到检查匹配的调用,但它相当快。ba,bastrncmp

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

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

4

4 回答 4

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;

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

SELECT c, MAX(val) AS max_val
FROM table
GROUP BY a, b;

如果子选择的结果是正确的,则运行您的完整查询。如果该结果是正确的,那么您应该执行以下操作:

ALTER TABLE `table` ADD INDEX abc_ndx (a,b,c,val);

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

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

更新 2012-11-27 13:46 EDT

您可以通过做两件事来访问索引而不接触表格

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

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

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

由于查询的所有列都在索引中,查询优化器只会触及索引(或预缓存索引页)。如果表是 MyISAM,您可以...

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

相信我,你真的不想违背 mysqld 的意愿访问索引页面。我的意思是什么?

对于 MyISAM,MyISAM 表的索引页存储在表的.MYI文件中。每个 DML 语句都会调用一个全表锁。

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

由于 MyISAM 需要恒定的 I/O 或 InnoDB 执行的恒定MVCC协议,您不必使用 Python、Perl、PHP、C++ 或 Java 来规避对索引页面的访问。

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

更新 2012-11-30 12:11 EDT

从你最后的评论

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

对于 InnoDB,MVCC 并没有让任何事情复杂化。它实际上可以成为你最好的朋友,前提是:

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

如果重复读取,我希望访问的索引页面几乎永远位于 InnoDB 缓冲池中。我只是确保您的innodb_buffer_pool_size设置得足够高以容纳必要的 InnoDB 数据

于 2012-11-19T20:43:30.303 回答
4

您可能无法直接访问密钥。我认为这实际上不会对性能产生任何影响。

如果您以正确的顺序设置覆盖索引,MySQL 将不会从硬盘中获取单个页面,而是直接从索引中传递结果。没有比这更快的了。

请注意,如果它的结果​​大于您的tmp_table_sizemax_heap_table_size ,您的子选择可能最终会出现在磁盘上的一个临时表中。

Created_tmp_tables_disk_tables如果不确定,请检查状态。

有关 MySQL 如何使用内部临时表的更多信息,您可以在此处找到 http://dev.mysql.com/doc/refman/5.5/en/internal-temporary-tables.html

如果需要,请发布您的表结构以供审核。

于 2012-11-14T22:16:58.183 回答
4

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

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

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

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

  • HailDB:让 NoSQL 可以访问 InnoDB 表,运行在 Embedded InnoDB 之上。见会议介绍编辑: HailDB 可能无法与 MySQL 并行运行。

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

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

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

于 2012-11-29T21:54:14.027 回答
0

没有。没有实用的方法来使用 MySQL 索引,从 C 程序中,以 MySQL 引擎以外的方式访问 MySQL 索引,以检查两个 (a,b) 对(键)是否相同或不。

还有更实用的解决方案,不需要访问 MySQL 引擎之外的 MySQL 数据文件或编写用户定义的函数。


Q:你知道mysql索引存放在文件系统的什么位置吗?

文件系统中索引的位置将取决于表的存储引擎。对于 MyISAM 引擎,索引存储在 datadir/database 目录下的 .MYI 文件中;InnoDB 索引存储在 InnoDB 管理的表空间文件中。f innodb_file_per_table 变量在创建表时设置,innodb_data_home_dir/database 子目录下的每个表都会有一个单独的 .ibd 文件。

问:你知道格式是什么吗?

每个存储引擎的存储格式不同,MyISAM、InnoDB等,也取决于版本。就 MySQL 对存储引擎的要求而言,我对数据的存储方式有一定的了解。有关内部的详细信息将特定于每个引擎。

问:是什么让它不切实际?

这是不切实际的,因为它需要大量工作,并且将取决于未来可能发生变化的存储引擎的细节。定义问题空间并编写返回所需内容的 SQL 语句会更加实用。

正如 Quassnoi 在他对您的问题的评论中指出的那样,您完全不清楚您通过创建 UDF 或从 MySQL 外部访问 MySQL 索引来解决什么特定问题。我确信 Quassnoi 将有一个很好的方法来完成您需要的高效 SQL 语句。

于 2012-11-29T23:06:26.967 回答