【问题标题】:Mysql wrong index after InnoDB compressionInnoDB压缩后Mysql错误索引
【发布时间】:2017-06-11 14:24:30
【问题描述】:

我有 2 台 mysql 服务器(主服务器和从服务器)。我在 Slave 上启用了 InnoDB 压缩,之后 mysql 有时会在查询中选择错误的索引。

大师讲解:

+----+-------------+--------+--------+------------- --+---------+---------+-------------- --+------------+----------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+--------+--------+------------- --+---------+---------+-------------- --+------------+----------+ | 1 |简单 | p |范围 |初级 |初级 | 8 |空 | 112017572 |使用位置 | | 1 |简单 | l | eq_ref |初级 |初级 | 8 | p.loan_ID | 1 |空 | | 1 |简单 |自动对焦 | eq_ref |初级 |初级 | 8 | p.fromAccount_ID | 1 |使用位置 | | 1 |简单 |在 | eq_ref |初级 |初级 | 8 | p.toAccount_ID | 1 |使用位置 | +----+-------------+--------+--------+------------- --+---------+---------+-------------- --+------------+----------+

对奴隶的解释:

+----+-------------+--------+--------+------------- -------------------------------------------------- ----------------+--------------------+---------+-- ---------------+--------+------------- ---------------------------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+--------+--------+------------- -------------------------------------------------- ----------------+--------------------+---------+-- ---------------+--------+------------- ---------------------------------+ | 1 |简单 | l |索引 |初级 | FK243910AAD869E6 | 9 |空 | 804876 |使用索引;使用临时的;使用文件排序 | | 1 |简单 | p |参考 |初级,FK4BE7532292C5D482,FK4BE75322AE503A13,FK4BE75322382D11BC,POSTING_DATE | FK4BE75322382D11BC | 9 | l.ID | 101 |使用索引条件;使用位置 | | 1 |简单 |自动对焦 | eq_ref |初级 |初级 | 8 | p.fromAccount_ID | 1 |使用位置 | | 1 |简单 |在 | eq_ref |初级 |初级 | 8 | p.toAccount_ID | 1 |使用位置 | +----+-------------+--------+--------+------------- -------------------------------------------------- ----------------+--------------------+---------+-- ---------------+--------+------------- ---------------------------------+
SELECT 
      p.ID AS 'payment_id',
      p.loan_ID AS 'loan_id',
      l.client_ID AS 'client_ID',
      p.amount AS 'amount',
      p.postingDate AS 'payment_date',
             CASE 
                 WHEN af.acc_type = 'POLCH' THEN 'wallet'    
                 WHEN af.acc_type = 'PLTCH' THEN 'wallet'        
                 WHEN af.acc_type = 'CNTT' THEN 'bank'        
                 WHEN af.acc_type = 'CNT2' THEN 'bank'        
                 WHEN af.acc_type = 'KONCH' THEN 'bank'        
                 WHEN af.acc_type = 'KRDTM' THEN 'cash'        
                 WHEN af.acc_type = 'LDRCH' THEN 'bank'        
                 ELSE concat('UNKNOWN_',af.acc_type) 
                 END AS 'payment_system_type', 
      af.description AS 'payment_system' 
      FROM Posting AS p 
      INNER JOIN Account AS af ON p.fromAccount_ID = af.ID 
      INNER JOIN Account AS at ON p.toAccount_ID = at.ID 
      INNER JOIN Loan AS l ON p.loan_id = l.ID 
      WHERE ( 
             af.acc_type = 'KONCH' 
             OR af.acc_type = 'PLTCH' 
             OR af.acc_type = 'POLCH' 
             OR af.acc_type = 'KRDTM' 
             OR  af.acc_type = 'LDRCH' 
             OR af.acc_type = 'CNT2' 
             OR af.acc_type = 'CNTT') 
             AND at.acc_type = 'ABON' 
             AND p.postingDate < DATE(now()) 
             AND p.ID > 0 
ORDER BY p.ID LIMIT 10000;

贷款 - l

发帖 - P

大师:

| Loan  | CREATE TABLE `Loan` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `amount` decimal(19,4) DEFAULT NULL,
  `amountToReturn` decimal(19,4) DEFAULT NULL,
  `isGivenOut` bit(1) DEFAULT b'0',
  `isPaid` bit(1) DEFAULT NULL,
  `issueDate` datetime DEFAULT NULL,
  `loanPeriod` int(11) DEFAULT NULL,
  `productType` varchar(255) DEFAULT NULL,
  `realPayDate` datetime DEFAULT NULL,
  `client_ID` bigint(20) DEFAULT NULL,
  `product_ID` bigint(20) DEFAULT NULL,
  `givenOutDate` datetime DEFAULT NULL,
  `isPaidByBank` bit(1) DEFAULT NULL,
  `accountNumberNBKI` varchar(255) DEFAULT NULL,
  `needManualProcessing` bit(1) DEFAULT NULL,
  `isReverted` bit(1) DEFAULT b'0',
  `showInNBCHReport` bit(1) DEFAULT b'1',
  `stake` decimal(19,5) DEFAULT NULL,
  `ignoreProlongation` bit(1) DEFAULT b'0',
  `stakeAfter21` decimal(19,5) DEFAULT NULL,
  `discount_id` bigint(20) DEFAULT NULL,
  `showInEquifaxReport` bit(1) DEFAULT b'1',
  `ignoreNbch` bit(1) DEFAULT b'0',
  PRIMARY KEY (`ID`),
  KEY `FK2439106EC0BA18` (`product_ID`),
  KEY `ISPAID_INDEX` (`isPaid`) USING BTREE,
  KEY `ISP_ISGOUT_INDEX` (`isPaid`,`isGivenOut`),
  KEY `ISSUEDATE_INDEX` (`issueDate`),
  KEY `FK243910735827C6` (`discount_id`),
  KEY `idx_Loan_realPayDate` (`realPayDate`),
  KEY `idx_Loan_givenOutDate` (`givenOutDate`),
  KEY `FK243910AAD869E6` (`client_ID`),
  CONSTRAINT `_FK243910735827C6` FOREIGN KEY (`discount_id`) REFERENCES `Discount` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2000623399 DEFAULT CHARSET=utf8 

 Posting | CREATE TABLE `Posting` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `amount` decimal(19,4) DEFAULT NULL,
  `postingDate` datetime DEFAULT NULL,
  `fromAccount_ID` bigint(20) DEFAULT NULL,
  `loan_ID` bigint(20) DEFAULT NULL,
  `toAccount_ID` bigint(20) DEFAULT NULL,
  `sourceType` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `FK4BE7532292C5D482` (`fromAccount_ID`),
  KEY `FK4BE75322AE503A13` (`toAccount_ID`),
  KEY `FK4BE75322382D11BC` (`loan_ID`),
  KEY `POSTING_DATE` (`postingDate`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=230996702 DEFAULT CHARSET=utf8 

从机:

| Loan  | CREATE TABLE `Loan` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `amount` decimal(19,4) DEFAULT NULL,
  `amountToReturn` decimal(19,4) DEFAULT NULL,
  `isGivenOut` bit(1) DEFAULT b'0',
  `isPaid` bit(1) DEFAULT NULL,
  `issueDate` datetime DEFAULT NULL,
  `loanPeriod` int(11) DEFAULT NULL,
  `productType` varchar(255) DEFAULT NULL,
  `realPayDate` datetime DEFAULT NULL,
  `client_ID` bigint(20) DEFAULT NULL,
  `product_ID` bigint(20) DEFAULT NULL,
  `givenOutDate` datetime DEFAULT NULL,
  `isPaidByBank` bit(1) DEFAULT NULL,
  `accountNumberNBKI` varchar(255) DEFAULT NULL,
  `needManualProcessing` bit(1) DEFAULT NULL,
  `isReverted` bit(1) DEFAULT b'0',
  `showInNBCHReport` bit(1) DEFAULT b'1',
  `stake` decimal(19,5) DEFAULT NULL,
  `ignoreProlongation` bit(1) DEFAULT b'0',
  `stakeAfter21` decimal(19,5) DEFAULT NULL,
  `discount_id` bigint(20) DEFAULT NULL,
  `showInEquifaxReport` bit(1) DEFAULT b'1',
  `ignoreNbch` bit(1) DEFAULT b'0',
  PRIMARY KEY (`ID`),
  KEY `FK2439106EC0BA18` (`product_ID`),
  KEY `ISPAID_INDEX` (`isPaid`) USING BTREE,
  KEY `ISP_ISGOUT_INDEX` (`isPaid`,`isGivenOut`),
  KEY `ISSUEDATE_INDEX` (`issueDate`),
  KEY `FK243910735827C6` (`discount_id`),
  KEY `idx_Loan_realPayDate` (`realPayDate`),
  KEY `idx_Loan_givenOutDate` (`givenOutDate`),
  KEY `FK243910AAD869E6` (`client_ID`),
  CONSTRAINT `_FK243910735827C6` FOREIGN KEY (`discount_id`) REFERENCES `Discount` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2000623399 DEFAULT CHARSET=utf8 
ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 

 Posting | CREATE TABLE `Posting` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `amount` decimal(19,4) DEFAULT NULL,
  `postingDate` datetime DEFAULT NULL,
  `fromAccount_ID` bigint(20) DEFAULT NULL,
  `loan_ID` bigint(20) DEFAULT NULL,
  `toAccount_ID` bigint(20) DEFAULT NULL,
  `sourceType` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`ID`),
  KEY `FK4BE7532292C5D482` (`fromAccount_ID`),
  KEY `FK4BE75322AE503A13` (`toAccount_ID`),
  KEY `FK4BE75322382D11BC` (`loan_ID`),
  KEY `POSTING_DATE` (`postingDate`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=230996702 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4  

如果从查询中删除表贷款

+----+-------------+--------+--------+------------- ---------------------------------------------------------------+-- --------+----------+------------------+-- ----------+--------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+--------+--------+------------- ---------------------------------------------------------------+-- --------+----------+------------------+-- ----------+--------------+ | 1 |简单 | p |范围 |初级,FK4BE7532292C5D482,FK4BE75322AE503A13,POSTING_DATE |初级 | 8 |空 | 107736559 |使用位置 | | 1 |简单 |自动对焦 | eq_ref |初级 |初级 | 8 | smsfinance.p.fromAccount_ID | 1 |使用位置 | | 1 |简单 |在 | eq_ref |初级 |初级 | 8 | smsfinance.p.toAccount_ID | 1 |使用位置 | +----+-------------+--------+--------+------------- ---------------------------------------------------------------+-- --------+----------+------------------+-- ----------+--------------+

如果我添加 在 Account(acc_type) 上创建索引帐户;

计划:

+----+-------------+--------+--------+------------- -------------------------------------------------- ----------------+--------------------+---------+-- ----------------------+------+------ ----------------------------------------------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+--------+--------+------------- -------------------------------------------------- ----------------+--------------------+---------+-- ----------------------+------+------ ----------------------------------------------------+ | 1 |简单 |自动对焦 |范围 |初级,acc |会计 | 21 |空 | 4192 |使用索引条件;使用临时的;使用文件排序 | | 1 |简单 | p |参考 |初级,FK4BE7532292C5D482,FK4BE75322AE503A13,FK4BE75322382D11BC,POSTING_DATE | FK4BE7532292C5D482 | 9 | smsfinance.af.ID | 54 |使用索引条件;使用位置 | | 1 |简单 | l | eq_ref |初级 |初级 | 8 | smsfinance.p.loan_ID | 1 |空 | | 1 |简单 |在 | eq_ref |初级,acc |初级 | 8 | smsfinance.p.toAccount_ID | 1 |使用位置 | +----+-------------+--------+--------+------------- -------------------------------------------------- ----------------+--------------------+---------+-- ----------------------+------+------ ----------------------------------------------------+

查询执行时间长。

【问题讨论】:

  • 发生这种情况的原因有很多。请为lp 提供SHOW CREATE TABLE,以及相关查询。我怀疑压缩是否相关。 mysqls 是什么版本?
  • 编辑主帖。

标签: mysql indexing compression innodb


【解决方案1】:

我怀疑压缩会导致不同的统计信息,从而导致不同的执行计划。

我认为在此查询中表 Loan 没有用处。从查询中删除它可能会强制解释计划相同。

每个表中有 200M 行?另一个加速是缩小表格。

  • 尽可能将 BIGINT(每个 8 字节)更改为 INT UNSIGNED(4 字节,范围 0.4 亿)。
  • 规范化_type 列,替换为SMALLINT UNSIGNED(2 字节,范围0..64K)或其他合适的整数类型。或者,如果存在有限的少量“类型”,则将该列转换为 ENUM

AccountINDEX(acc_type) 吗? (或者至少 以 acc_type 开始。)

删除INNER JOIN Loan AS l ON p.loan_id = l.ID 并将l.client_ID AS 'client_ID', 替换为

( SELECT client_ID FROM Loans WHERE ID = p.loan_id ) AS 'client_ID',

我认为这将强制执行不同的查询计划,也许是一个不错的计划。

【讨论】:

  • 对不起,我查询有误。现在查询中存在表 Loan。
  • 否,帐户的索引为 acc_type 和 client_ID' UNIQUE KEY idx_unique_client_acc_type (client_ID,acc_type)'
  • 我需要一个以 acc_type 开头的索引开始
  • 查看我添加的处理贷款的建议。
  • Loan的好办法,但我不明白mysql为什么改变计划?以及如何防止这种变化?因为我必须更改另一个查询。
猜你喜欢
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 1970-01-01
  • 2015-05-24
  • 2017-03-24
  • 1970-01-01
  • 2017-11-27
  • 1970-01-01
相关资源
最近更新 更多