草庐IT

MySQL 主键对顺序影响 JOIN 速度

coder 2023-10-13 原文

我在 MySQL 中有 3 个表:

innodb_verion     1.1.8
version           5.5.29-log
Table: artist
Columns:
    id              int(11)
    new_id          varchar(50)
Table: collection
Columns:
    id              int(11)
    new_id          varchar(50)
Table: artist_collection
Columns:
    artist_id       int(11) PK
    collection_id   int(11) PK

艺术家和收藏表包含 100 行(我只是提取了一个子集来测试这个问题)

artist_collection 表包含超过 800 万行,并且主键创建为:

ALTER TABLE artist_collection ADD PRIMARY KEY (artist_id,collection_id);

当我对艺术家和收藏进行相同的连接时,收藏比艺术家花费的时间要长得多:

SELECT artist.new_id AS 'i' FROM artist INNER JOIN artist_collection ON artist.id=artist_collection.artist_id LIMIT 100;
100 row(s) returned  0.001 sec
SELECT collection.new_id AS 'i' FROM collection INNER JOIN artist_collection ON collection.id=artist_collection.collection_id LIMIT 100;
100 row(s) returned  2.636 sec

这很重要,因为这些原始表有超过 1000 万行,我不想在我的查询中使用 LIMIT。即使我执行了 LIMIT 1000,慢速查询也需要大约 35 秒才能完成,而快速查询大约需要 0.020 秒。然后我对两个查询都进行了 EXPLAIN EXTENDED 以查看实际情况:

EXPLAIN EXTENDED SELECT artist.id AS 'i' FROM artist INNER JOIN artist_collection ON artist.id=artist_collection.artist_id LIMIT 100;

id    select_type    table              type    possible_keys    key      key_len    ref              rows    filtered    Extra
1     SIMPLE         artist             ALL     NULL             NULL     NULL       NULL             82      100.00
1     SIMPLE         artist_collection  ref     PRIMARY          PRIMARY  4          tbl.artist.id    2       100.00      Using index
EXPLAIN EXTENDED SELECT collection.id AS 'i' FROM collection INNER JOIN artist_collection ON collection.id=artist_collection.collection_id LIMIT 100;

id    select_type    table              type    possible_keys    key      key_len    ref      rows     filtered    Extra
1     SIMPLE         collection         ALL     NULL             NULL     NULL       NULL     101      100.00
1     SIMPLE         artist_collection  index   NULL             PRIMARY  8          NULL     8725465  100.00      Using where; Using index; Using join buffer

如您所见,它并没有平等对待查询。然后我跑了:

ALTER TABLE artist_collection DROP PRIMARY KEY;
ALTER TABLE artist_collection ADD PRIMARY KEY (collection_id,artist_id);

这导致问题自行逆转,现在艺术家 JOIN 花费了很长时间。所以我的问题是:

1) MySQL 是否以不同方式解释 PRIMARY KEY 的第一个和第二个条目?
2) 到底发生了什么?
3) 如何使查询相等(快速)?

最佳答案

考虑以这种方式存储的复合索引中的记录:

+---------------+-----------+
| collection_id | artist_id |
+---------------+-----------+
|             1 |         1 |
|             1 |         2 |
|             1 |         3 |
|             2 |         1 |
|             2 |         2 |
|             3 |         1 |
+---------------+-----------+

鉴于数据首先按 collection_id 排序,查找所有 collection_id = 1 非常简单。但是,查找所有 artist_id 不是。

即使您同时搜索 collection_id = 1 和 artist_id = 1,这也是一项简单的任务(您不需要扫描所有 artist_id 值) .

MySQL 也发生了类似的事情。当您仅通过 collection_id 加入时,此索引非常有用。当您同时通过 collection_idartist_id 加入时,此索引再次有用。但是,当仅加入 artist_id 时,此索引不会有太大帮助。

如果您也打算仅加入 artist_id,那么您可能需要在 artist_id 上添加另一个索引。您应该在您的 exaplain 中看到该新索引将用于这些查询。

关于MySQL 主键对顺序影响 JOIN 速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19842869/

有关MySQL 主键对顺序影响 JOIN 速度的更多相关文章

  1. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

  2. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

    我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

  3. 使用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

  4. ruby-on-rails - 在 RSpec 中,如何以任意顺序期望具有不同参数的多条消息? - 2

    RSpec似乎按顺序匹配方法接收的消息。我不确定如何使以下代码工作:allow(a).toreceive(:f)expect(a).toreceive(:f).with(2)a.f(1)a.f(2)a.f(3)我问的原因是a.f的一些调用是由我的代码的上层控制的,所以我不能对这些方法调用添加期望。 最佳答案 RSpecspy是测试这种情况的一种方式。要监视一个方法,用allowstub,除了方法名称之外没有任何约束,调用该方法,然后expect确切的方法调用。例如:allow(a).toreceive(:f)a.f(2)a.f(1)

  5. .net - .NET 将如何影响 Python 和 Ruby 应用程序? - 2

    我很好奇.NET将如何影响Python和Ruby应用程序。用IronPython/IronRuby编写的应用程序是否会非常特定于.NET环境,以至于它们实际上将变得特定于平台?如果他们不使用任何.NET功能,那么IronPython/IronRuby相对于非.NET同类产品的优势是什么? 最佳答案 我不能说任何关于IronRuby的东西,但是大多数Python实现(如IronPython、Jython和PyPy)都试图尽可能忠实于CPython实现。不过,IronPython正在迅速成为这方面的佼佼者之一,并且在PlanetPyth

  6. ruby-on-rails - 无法安装 mysql2 0.3.14 gem - 2

    我看到其他人也遇到过类似的问题,但没有一个解决方案对我有用。0.3.14gem与其他gem文件一起存在。我已经完全按照此处指示完成了所有操作:https://github.com/brianmario/mysql2.我仍然得到以下信息。我不知道为什么安装程序指示它找不到include目录,因为我已经检查过它存在。thread.h文件存在,但不在ruby​​目录中。相反,它在这里:C:\RailsInstaller\DevKit\lib\perl5\5.8\msys\CORE\我正在运行Windows7并尝试在Aptana3中构建我的Rails项目。我的Ruby是1.9.3。$gemin

  7. ruby - 按数字(从大到大)然后按字母(字母顺序)对对象集合进行排序 - 2

    我正在构建一个小部件来显示奥运会的奖牌数。我有一个“国家”对象的集合,其中每个对象都有一个“名称”属性,以及奖牌计数的“金”、“银”、“铜”。列表应该排序:1.首先是奖牌总数2.如果奖牌相同,按类型分割(金>银>铜,即2金>1金+1银)3.如果奖牌和类型相同,则按字母顺序子排序我正在用ruby​​做这件事,但我想语言并不重要。我确实找到了一个解决方案,但如果感觉必须有更优雅的方法来实现它。这是我做的:使用加权奖牌总数创建一个虚拟属性。因此,如果他们有2个金牌和1个银牌,加权总数将为“3.020100”。1金1银1铜为“3.010101”由于我们希望将奖牌数排序为最高的,因此列表按降序排

  8. ruby - 如何使用 ruby​​ mysql2 执行事务 - 2

    我已经开始使用mysql2gem。我试图弄清楚一些基本的事情——其中之一是如何明确地执行事务(对于批处理操作,比如多个INSERT/UPDATE查询)。在旧的ruby-mysql中,这是我的方法:client=Mysql.real_connect(...)inserts=["INSERTINTO...","UPDATE..WHEREid=..",#etc]client.autocommit(false)inserts.eachdo|ins|beginclient.query(ins)rescue#handleerrorsorabortentirelyendendclient.commi

  9. ruby - 以随机顺序将数组拆分为多个数组 - Ruby - 2

    我试图在每次运行时以随机顺序将一个名称数组拆分为多个数组。我知道如何拆分它们:name_array=["bob","john","rob","nate","nelly","michael"]array=name_array.each_slice(2).to_a=>[["bob","john"],["rob","nate"],["nelly","michael"]]但是,如果我希望它每次都以随机顺序吐出它们怎么办? 最佳答案 在做同样的事情之前,打乱数组。(Array#shuffle)name_array.shuffle.each_s

  10. ruby - 关于 Ruby 中 Dir[] 和 File.join() 的混淆 - 2

    我在Ruby中遇到了一个关于Dir[]和File.join()的简单程序,blobs_dir='/path/to/dir'Dir[File.join(blobs_dir,"**","*")].eachdo|file|FileUtils.rm_rf(file)ifFile.symlink?(file)我有两个困惑:首先,File.join(@blobs_dir,"**","*")中的第二个和第三个参数是什么意思?其次,Dir[]在Ruby中有什么用?我只知道它等价于Dir.glob(),但是,我对Dir.glob()确实不是很清楚。 最佳答案

随机推荐