AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 188091
Accepted
Yunus UYANIK
Yunus UYANIK
Asked: 2017-10-11 02:35:39 +0800 CST2017-10-11 02:35:39 +0800 CST 2017-10-11 02:35:39 +0800 CST

使用索引的 MySQL 查询性能

  • 772

Campaign Code 表中有 7700 万条记录。

指数声明:

索引 IDX_CampaignCode_Id_CodeDateId_CodeId_CustomerId

(CampaignId, CampaignCodeDateId, PKCampaignCodeId, CustomerId)

第一次查询,执行时间:0:00:0.546

SELECT
 cc.*
FROM CampaignCode cc
WHERE cc.CampaignId = 18
AND cc.CampaignCodeDateId = 19325
ORDER BY cc.PKCampaignCodeId LIMIT 20000 OFFSET 0;

在此处输入图像描述

第二个查询,执行时间:0:01:11.597

SELECT
 cc.*
FROM CampaignCode cc
WHERE cc.CampaignId = 30
AND cc.CustomerId is not null
ORDER BY cc.PKCampaignCodeId LIMIT 25 OFFSET 0

在此处输入图像描述

第二个问题不需要更快吗?我应该怎么办?

编辑 :

我为第二个查询创建了索引。

INDEX IDX_Test_Index

(CampaignId, CustomerId,PKCampaignCodeId)

创建索引后,第二个查询更快,但第一个查询更慢

第一个查询执行计划已更改:执行时间:0:01:17.236 在此处输入图像描述

CREATE TABLE CampaignCode (
  PKCampaignCodeId int(11) NOT NULL AUTO_INCREMENT,
  CampaignId int(11) NOT NULL,
  Code varchar(255) NOT NULL,
  CreatedBy int(11) NOT NULL,
  CreatedOn datetime NOT NULL,
  CustomerId int(11) DEFAULT NULL,
  IsActive bit(1) NOT NULL,
  IsUsed bit(1) DEFAULT NULL,
  ModifiedBy int(11) DEFAULT NULL,
  ModifiedOn datetime DEFAULT NULL,
  OrderNumber varchar(255) DEFAULT NULL,
  CampaignCodeDateId int(11) NOT NULL,
  PRIMARY KEY (PKCampaignCodeId),
  INDEX IDX_CampaignCode_CampaignId (CampaignId),
  INDEX IDX_CampaignCode_CampaignId_CodeDateId_CodeId_CampaignCodeId
            (CampaignId, CampaignCodeDateId, PKCampaignCodeId),
  INDEX IDX_CampaignCode_Code (Code),
  INDEX IDX_Test_Index (CampaignId, CustomerId, PKCampaignCodeId)
)
ENGINE = INNODB
AUTO_INCREMENT = 114306664
AVG_ROW_LENGTH = 61
CHARACTER SET latin5
COLLATE latin5_turkish_ci
ROW_FORMAT = DYNAMIC;
mysql index
  • 3 3 个回答
  • 115 Views

3 个回答

  • Voted
  1. Best Answer
    Rick James
    2017-10-11T15:38:05+08:002017-10-11T15:38:05+08:00

    没有完美的索引:

    WHERE cc.CampaignId = 30
      AND cc.CustomerId is not null
    ORDER BY cc.PKCampaignCodeId
    

    这是因为索引无法通过IS NOT NULL以到达ORDER BY.

    一般来说,

    WHERE a=1 AND b=2 ORDER BY c
    

    可以充分利用INDEX(a,b,c)或(b,a,c)

    但是,这不能:

    WHERE a=1 AND b!=2 ORDER BY c
    

    (IS NOT NULL类似于!= 2它是一个“范围”,而不是单个值。)

    要对此进行优化:

    WHERE cc.CampaignId = 30
      AND cc.CustomerId is not null
    ORDER BY cc.PKCampaignCodeId LIMIT 25 OFFSET 0
    

    有两种可能性。优化器会选择一个,有时是不太理想的一个:

    INDEX(CampaignId, CustomerId)
    INDEX(CampaignId, PKCampaignCodeId)
    

    第一个会做过滤,但仍然需要排序和限制。
    第二个将进行一些过滤,避免排序,但可能需要查看超过 25 行的内容。

    索引中包含所有 3 列没有任何好处;第三列将不会被使用。(而且,显然,它会给您的第一个SELECT.

    有关创建索引的更多信息:http: //mysql.rjweb.org/doc.php/index_cookbook_mysql (尽管它没有完全解决您的所有问题)

    • 2
  2. KumarHarsh
    2017-10-11T03:08:35+08:002017-10-11T03:08:35+08:00

    第二个问题不需要更快吗?我应该怎么办?

    没有第二个查询不会使用索引,因为在复合非聚集索引中条件很重要的排序和列。

    因此,为了在第二个查询中使用索引,您应该使用另一个复合非聚集索引。

    INDEX IDX_CampaignCode_Id_CodeDateId_CodeId_CustomerId1
    
    (CampaignId, CustomerId,PKCampaignCodeId)
    
    SELECT
     cc.*
    FROM CampaignCode cc
    WHERE cc.CampaignId = 30
    AND cc.CustomerId is not null
    ORDER BY cc.PKCampaignCodeId LIMIT 25 OFFSET 0
    

    还要避免使用 *,改用列名。

    • 0
  3. anisakras
    2017-10-12T06:15:10+08:002017-10-12T06:15:10+08:00

    第二个查询甚至不使用索引,而是使用 PRIMARY KEY。如果您在表上没有太多写入,您可以保留两个索引,因此 INDEX IDX_CampaignCode_CampaignId_CodeDateId_CodeId_CampaignCodeId(CampaignId、CampaignCodeDateId、PKCampaignCodeId)和 INDEX IDX_Test_Index(CampaignId、CustomerId、PKCampaignCodeId)。

    如果您需要其他建议,请参考此处的索引:INDEX IDX_CampaignCode_CampaignId (CampaignId) 是多余的。它不会被使用,您可以将其丢弃。

    • 0

相关问题

  • 是否有任何 MySQL 基准测试工具?[关闭]

  • 我在哪里可以找到mysql慢日志?

  • 如何优化大型数据库的 mysqldump?

  • 什么时候是使用 MariaDB 而不是 MySQL 的合适时机,为什么?

  • 组如何跟踪数据库架构更改?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve