草庐IT

mysql - 有索引的查询比没有索引慢

coder 2023-10-19 原文

我使用的是 MySQL 5.6,我的存储引擎是 InnoDB。

我有一个包含 100 万行的表,其中包含以下列:

  • ID(主键)
  • 名字
  • 姓氏
  • foreign_key_id(外键,非空)
  • foreign_key_id2(另一个外键,默认为NULL)

行在下面分隔:

  • 25% foreign_key_id 值为 1 且 foreign_key_id2 NULL
  • 25% foreign_key_id 值为 1 且 foreign_key_id2 NOT NULL
  • 25% foreign_key_id 值为 2 且 foreign_key_id2 NULL
  • 25% foreign_key_id 值为 2 且 foreign_key_id2 NOT NULL

具有以下指标:

  • foreign_key_id 上索引 foreign_key_idx
  • 索引 foreign_key_2_idxforeign_key_id2
  • (foreign_key_idx, foreign_key_2_idx) 上的复合索引 foreign_key_comp_idx

我执行以下查询:

Query 1 - without indexes:

SELECT *
FROM table tbl
IGNORE INDEX(foreign_key_idx, foreign_key_2_idx, foreign_key_comp_idx)
WHERE tbl.foreign_key_id = 1 AND tbl.foreign_key_id2 IS NOT NULL

Query 2 - with indexes (no composite index):

SELECT *
FROM table tbl
IGNORE INDEX(foreign_key_comp_idx)
WHERE tbl.foreign_key_id = 1 AND tbl.foreign_key_id2 IS NOT NULL

Query 3 - with composite index (no other indexes):

SELECT *
FROM table tbl
IGNORE INDEX(foreign_key_idx, foreign_key_2_idx)
WHERE tbl.foreign_key_id = 1 AND tbl.foreign_key_id2 IS NOT NULL

结果:

Query 1 (no indexes) performs a full table scan and uses 1 million records with a total duration of 0.37 seconds.

Query 2 (indexes, no composite index) performs a non-unique key lookup on foreign_key_idx index and uses 500K records with a total duration of 0.6 seconds.

Query 3 (composite index only) performs an index range scan on composite index and uses 480K records with a total duration of 0.13 seconds.

我真正不明白的是:为什么query 2(有索引)总是比query 1(没有索引)执行得慢?我真的真的卡住了,需要一些帮助......

我已经用不同数量的行测试了上面的查询,例如 1k、10k、20k、50k、100k、200k、250k、500k、1M 等,始终具有相同的比率 (25%),结果是相同(查询 2 总是执行缓慢)

提前致谢,非常感谢任何类型的输入!

编辑(2016 年 5 月 2 日)

显示创建表命令:

CREATE TABLE `table` (
   `ID` int(11) NOT NULL AUTO_INCREMENT,
   `FirstName` varchar(255) NOT NULL,
   `LastName` varchar(255) NOT NULL,
   `foreign_key_id` int(11) NOT NULL,
   `foreign_key_id2` int(11) DEFAULT NULL,

   PRIMARY KEY (`ID`),
   KEY `foreign_key_idx` (`foreign_key_id`),
   KEY `foreign_key_2_idx` (`foreign_key_id2`),
   KEY `foreign_key_comp_idx ` (`foreign_key_id`,`foreign_key_id2`),

   CONSTRAINT `foreign_key_idx` FOREIGN KEY (`foreign_key_id`) REFERENCES `table2` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
   CONSTRAINT `foreign_key_2_idx` FOREIGN KEY (`foreign_key_id2`) REFERENCES `table3` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
 ) ENGINE=InnoDB AUTO_INCREMENT=1515998 DEFAULT CHARSET=latin1

解释计划:

不确定是否重要,但表 2 有 20 条记录,表 3 也有 100 万条。

最佳答案

让我吃惊的是查询 3 比查询 1 更快 :-)

您需要表中 25% 的记录。因此,简单地按顺序阅读表格应该是最快的方法。 (至少这是我会做的,也是大多数 DBMS 在那种情况下所做的。)

使用复合索引就可以了,因为知道选择哪些记录就足够了。但是,遍历一棵树只得到所有记录中的 25%,必须一条一条访问,这似乎是一项艰巨的任务。如前所述,令人惊讶的是,它比全表扫描运行得更快。也许物理记录恰好是按需要排序的,所以你不必从一个部分到另一个部分来回移动,这是从索引中获取时通常会发生的情况。 (解释:假设您在磁盘上的表部分 A 的索引中找到匹配的记录引用,下一个匹配恰好在扇区 B,第三个再次在扇区 A,......这可能需要很长时间。如果你是然而,幸运的是,您首先在一个扇区中找到所有记录,然后在另一个扇区中找到。通过全表扫描,您可以逐个读取扇区,而不必从一个扇区切换到另一个扇区并返回。因此,全表扫描可以保证相当快,而通过索引访问可能快也可能慢。)

现在查询2:索引只指向可能匹配的记录(表中50%的记录,其中只有一半是匹配的)。这意味着您必须按照描述遍历树,只是为了仍然读取表的一半记录。这工作量太大了。

关于mysql - 有索引的查询比没有索引慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36970194/

有关mysql - 有索引的查询比没有索引慢的更多相关文章

  1. ruby - ECONNRESET (Whois::ConnectionError) - 尝试在 Ruby 中查询 Whois 时出错 - 2

    我正在用Ruby编写一个简单的程序来检查域列表是否被占用。基本上它循环遍历列表,并使用以下函数进行检查。require'rubygems'require'whois'defcheck_domain(domain)c=Whois::Client.newc.query("google.com").available?end程序不断出错(即使我在google.com中进行硬编码),并打印以下消息。鉴于该程序非常简单,我已经没有什么想法了-有什么建议吗?/Library/Ruby/Gems/1.8/gems/whois-2.0.2/lib/whois/server/adapters/base.

  2. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  3. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

  6. 没有类的 Ruby 方法? - 2

    大家好!我想知道Ruby中未使用语法ClassName.method_name调用的方法是如何工作的。我头脑中的一些是puts、print、gets、chomp。可以在不使用点运算符的情况下调用这些方法。为什么是这样?他们来自哪里?我怎样才能看到这些方法的完整列表? 最佳答案 Kernel中的所有方法都可用于Object类的所有对象或从Object派生的任何类。您可以使用Kernel.instance_methods列出它们。 关于没有类的Ruby方法?,我们在StackOverflow

  7. ruby-on-rails - Rails 3,嵌套资源,没有路由匹配 [PUT] - 2

    我真的为这个而疯狂。我一直在搜索答案并尝试我找到的所有内容,包括相关问题和stackoverflow上的答案,但仍然无法正常工作。我正在使用嵌套资源,但无法使表单正常工作。我总是遇到错误,例如没有路线匹配[PUT]"/galleries/1/photos"表格在这里:/galleries/1/photos/1/edit路线.rbresources:galleriesdoresources:photosendresources:galleriesresources:photos照片Controller.rbdefnew@gallery=Gallery.find(params[:galle

  8. ruby-on-rails - 有没有办法为 CarrierWave/Fog 设置上传进度指示器? - 2

    我在Rails应用程序中使用CarrierWave/Fog将视频上传到AmazonS3。有没有办法判断上传的进度,让我可以显示上传进度如何? 最佳答案 CarrierWave和Fog本身没有这种功能;你需要一个前端uploader来显示进度。当我不得不解决这个问题时,我使用了jQueryfileupload因为我的堆栈中已经有jQuery。甚至还有apostonCarrierWaveintegration因此您只需按照那里的说明操作即可获得适用于您的应用的进度条。 关于ruby-on-r

  9. ruby - 没有类方法获取 Ruby 类名 - 2

    如何在Ruby中获取BasicObject实例的类名?例如,假设我有这个:classMyObjectSystem我怎样才能使这段代码成功?编辑:我发现Object的实例方法class被定义为returnrb_class_real(CLASS_OF(obj));。有什么方法可以从Ruby中使用它? 最佳答案 我花了一些时间研究irb并想出了这个:classBasicObjectdefclassklass=class这将为任何从BasicObject继承的对象提供一个#class您可以调用的方法。编辑评论中要求的进一步解释:假设你有对象

  10. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

随机推荐