添加 where 条件后,Mysql 查询需要永远

Rah*_*hul 5 mysql performance optimization query-performance

我有一个 mysql 查询,它在 4 秒内返回结果。

SELECT 
    *
FROM
    xercasehistory
WHERE
    xerId = 192             
ORDER BY id DESC limit 10;
Run Code Online (Sandbox Code Playgroud)

但是当我向现有参数添加额外的 where 参数时,大约需要 30 秒才能完成。

SELECT 
    *
FROM
    xercasehistory
WHERE
    xerId = 192 AND type = 'case'
        AND fieldName = 'statusCode'
        AND typesKey=5            
ORDER BY id DESC limit 10;
Run Code Online (Sandbox Code Playgroud)

因此,我通过运行检查同一张表中的索引 show indexes from xercasehistory

xercasehistory 0 PRIMARY 1 ID A 24545933 BTREE
xercasehistory 1 xecasehistory_caseId_IDX 1 caseId A 2045494 BTREE
xercasehistory 1 xecasehistory_typeskey 1 typesKey A 20169 是 BTREE
xercasehistory 1 xecasehistory_active_govtId 1 活动 A 2 BTREE
xercasehistory 1 xecasehistory_active_govtId 2 govtId A 39336 BTREE
xercasehistory 1 xecasehistory_type 1 A 型 7721 BTREE
xercasehistory 1 xercasehistory_entryDate 1 entryDate A 24545933 BTREE
xercasehistory 1 xercasehistory_fieldName 1 fieldName A 14304 是 BTREE
xercasehistory 1 xercasehistory_recordTable 1 recordTable A 11406 是 BTREE
xercasehistory 1 xerId 1 xerId A 47113 是 BTREE
xercasehistory 1 govtId 1 govtId A 34329 BTREE

我们可以在 where 子句 (xerId,type,type,typesKey) 中使用的所有字段中看到一个索引。现在的问题是我期待更短的等待时间,因为它已经过滤了数据,xerId = 192所以剩余的 where 条件应该对已经过滤的记录起作用xerId = 192。请帮忙

的输出SHOW CREATE TABLE xercasehistory;

CREATE TABLE `xercasehistory` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `govtId` int(11) NOT NULL DEFAULT '0',
  `caseId` int(11) NOT NULL DEFAULT '0',
  `type` varchar(100) NOT NULL DEFAULT '',
  `notes` text NOT NULL,
  `entryDate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
  `employeeId` int(11) NOT NULL DEFAULT '0',
  `typesKey` int(7) DEFAULT '0',
  `logLevel` int(11) NOT NULL DEFAULT '1000',
  `dataType` int(11) NOT NULL DEFAULT '0',
  `recordTable` varchar(100) DEFAULT NULL,
  `old_recordId` int(11) DEFAULT NULL,
  `new_recordId` int(11) DEFAULT NULL,
  `fieldName` varchar(100) DEFAULT NULL,
  `old_int` int(11) DEFAULT NULL,
  `old_varchar` varchar(255) DEFAULT NULL,
  `old_text` text,
  `old_float` float DEFAULT NULL,
  `old_date` datetime DEFAULT NULL,
  `new_int` int(11) DEFAULT NULL,
  `new_varchar` varchar(255) DEFAULT NULL,
  `new_text` text,
  `new_float` float DEFAULT NULL,
  `new_date` datetime DEFAULT NULL,
  `more_details` tinyint(4) NOT NULL DEFAULT '0',
  `active` tinyint(4) NOT NULL DEFAULT '1',
  `xerId` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `xecasehistory_caseId_IDX` (`caseId`),
  KEY `xecasehistory_typeskey` (`typesKey`),
  KEY `xecasehistory_active_govtId` (`active`,`govtId`),
  KEY `xecasehistory_type` (`type`),
  KEY `xercasehistory_entryDate` (`entryDate`),
  KEY `xercasehistory_fieldName` (`fieldName`),
  KEY `xercasehistory_recordTable` (`recordTable`),
  KEY `xerId` (`xerId`),
  KEY `govtId` (`govtId`)
) ENGINE=InnoDB AUTO_INCREMENT=29726001 DEFAULT CHARSET=latin1
Run Code Online (Sandbox Code Playgroud)

解释第一次查询的结果

id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
'1', 'SIMPLE', 'xercasehistory', 'ref', 'xerId', 'xerId', '5', 'const', '1256458', '使用地点'

解释第二个查询的结果

id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
'1', 'SIMPLE', 'xercasehistory', 'range', 'xecasehistory_typeskey,xecasehistory_type,xercasehistory_fieldName,xerId', 'xerId', '5', NULL, '1256458', '使用索引条件; 使用 where'

ype*_*eᵀᴹ 4

对于第一个查询:

SELECT 
    *
FROM
    xercasehistory
WHERE
    xerId = 192             
ORDER BY 
    id DESC 
LIMIT 10;
Run Code Online (Sandbox Code Playgroud)

如果表是 InnoDB,则需要在(xerId, id)- 上建立索引。(xerId)对于如此简单且返回不超过 10 行的查询来说,四秒是一个非常长的时间。添加该索引并重试。查询时间应降至几毫秒。


对于第二个查询:

SELECT 
    *
FROM
    xercasehistory
WHERE
        xerId = 192 
    AND type = 'case'
    AND fieldName = 'statusCode'
    AND typesKey = 5            
ORDER BY 
    id DESC 
LIMIT 10 ;
Run Code Online (Sandbox Code Playgroud)

相同的索引会很有用。如果使用相同索引的此查询的效率不是很高(几毫秒),则可能有许多(数千)行与索引 ( xerId = 192) 匹配,但与所有 4 个条件匹配的行并不多,因此更合适的索引(在所有4 列 + id) 会更有效。


至于:

我们可以在where子句中使用的所有字段中看到索引(xerId,type,type,typesKey)...

不,没有综合索引。每列有 4 个索引。

为什么(xerId)不使用索引,至少对于第一个查询来说很奇怪。我会将其替换为索引(xerId, Id),然后检查 EXPLAIN 输出。