首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >MySQL为什么更新0行速度慢?

MySQL为什么更新0行速度慢?
EN

Database Administration用户
提问于 2018-03-07 00:27:12
回答 3查看 645关注 0票数 2

Update: where子句是相同的。结果概述如下。

以下查询在0.1s内运行,并返回0结果。

代码语言:javascript
复制
SELECT id from content WHERE compliance_overridden = 1 AND compliance_overridden_date < DATE_SUB(NOW(), INTERVAL 30 DAY);

因此,我希望在同一时间内返回以下查询(因为它实际上不需要更新任何内容)。

代码语言:javascript
复制
UPDATE content SET compliance_overridden = 0 WHERE compliance_overridden = 1 AND compliance_overridden_date < DATE_SUB(NOW(), INTERVAL 30 DAY);

它需要几分钟才能完成。

( a)为什么?

使用EXPLAIN显示,第一个查询不使用任何索引(key=None),但第二个查询是(key=PRIMARY)。更让我困惑的是。

( b)为什么一个查询使用一个索引,而另一个则不使用?也许MySQL先选择行,然后按主键进行更新?我尝试分别运行这两个查询(选择ids,然后更新),两者都运行得很快。

( c)为什么第二个查询在使用主索引时比没有索引时更慢?

PS:我尝试将USE INDEX (PRIMARY)添加到第一个查询中,IGNORE INDEX (PRIMARY)添加到第二个查询中,两者都对查询时间没有影响。

PPS:对第一个查询使用SQL_NO_CACHE也不影响查询时间。

引擎: Aurora MySQL 5.6.10a

SHOW创建表内容;

代码语言:javascript
复制
CREATE TABLE `content` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) NOT NULL,
  `content_key` char(40) NOT NULL,
  `body` mediumtext,
  `original_body` mediumtext,
  `meta` mediumblob,
  `status` enum('approved','deleted','draft','library','flagged','in progress','pending','published','publishing error','queued','ready','retracted','scheduled','removed','for review','reviewed','disabled') NOT NULL DEFAULT 'in progress',
  `is_flagged` int(11) NOT NULL DEFAULT '0',
  `extraction_status` enum('queued','processing','processed','processing error') DEFAULT NULL,
  `type` enum('internal','external','library') NOT NULL DEFAULT 'internal',
  `compliance_status` enum('ok','error','warning','unchecked','fail','overridden-ok','overridden-error','queued') DEFAULT 'unchecked' COMMENT 'Status when content is reviewed against guidelines',
  `queued_for_compliance` tinyint(4) NOT NULL DEFAULT '0',
  `queued_date` timestamp NULL DEFAULT NULL,
  `review_retries` int(11) NOT NULL,
  `review_notes` varchar(255) DEFAULT NULL,
  `needs_review` tinyint(1) DEFAULT '0' COMMENT 'Indicates that the content items needs the compliance reviewed to be checked',
  `pushed_for_review` enum('no','yes','error') NOT NULL DEFAULT 'no' COMMENT 'Flags if content is pushed to Minerva.',
  `risk_score` tinyint(1) DEFAULT '0',
  `keywords` text,
  `track` varchar(60) DEFAULT NULL,
  `purpose` enum('arbitrary','compliance_file_check','compliance_text_check','document','promotion','reply','retweet','site','site_post','soa','status_update','url') NOT NULL DEFAULT 'site' COMMENT 'Changed to an enum with applicable values. This will allow us to optimise queries on this column.',
  `purpose_note` text COMMENT 'Optional note explaining the purpose of this item',
  `format` varchar(20) DEFAULT NULL,
  `media` varchar(255) DEFAULT NULL,
  `media_alternate` varchar(255) DEFAULT NULL,
  `mime_type` varchar(255) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  `tag_id` int(11) DEFAULT NULL,
  `email_template_id` int(11) DEFAULT NULL,
  `social_account_id` int(11) DEFAULT NULL,
  `target_social_account_id` int(11) DEFAULT NULL,
  `parent_id` int(11) DEFAULT NULL,
  `notes` text,
  `options` text,
  `compliance_notes` text,
  `notified` tinyint(1) NOT NULL COMMENT 'Indicates if legal have been notified of the content change',
  `publish_immediately` tinyint(1) DEFAULT '0',
  `score` int(11) DEFAULT NULL,
  `insights` text,
  `publish_date` timestamp NULL DEFAULT NULL,
  `date_published` timestamp NULL DEFAULT NULL,
  `external_id` varchar(40) DEFAULT NULL,
  `feed_id` int(11) DEFAULT NULL,
  `site_id` int(11) DEFAULT NULL,
  `client_id` int(11) DEFAULT NULL,
  `has_changed` tinyint(1) DEFAULT '0' COMMENT 'Indicates if the content has ever changed',
  `was_flagged` tinyint(4) NOT NULL DEFAULT '0',
  `last_flagged` timestamp NULL DEFAULT NULL COMMENT 'Date content was last flagged',
  `compliance_overridden` tinyint(4) NOT NULL DEFAULT '0',
  `compliance_overridden_date` timestamp NULL DEFAULT NULL,
  `was_risky` tinyint(1) DEFAULT '0' COMMENT 'Indicates if the content was ever risky',
  `last_risky` timestamp NULL DEFAULT NULL COMMENT 'Date content was last assigned risk',
  `reference_urls` enum('none','ok','unchecked','error') NOT NULL DEFAULT 'none',
  `screenshot_url` text,
  `rescan` enum('no','manual-queued','compliance-changed','compliance-unchanged','compliance-unchecked') NOT NULL DEFAULT 'no',
  `rescan_rules` varchar(50) DEFAULT NULL,
  `applicable_rules` text COMMENT 'Applicable rules for a review',
  `lsh_hash` char(70) DEFAULT NULL,
  `comment_count` int(11) NOT NULL DEFAULT '0',
  `modified` timestamp NULL DEFAULT NULL,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `content_key` (`content_key`),
  KEY `fk_content_user` (`user_id`),
  KEY `fk_content_content` (`parent_id`),
  KEY `fk_content_email_template` (`email_template_id`),
  KEY `fk_content_target_social_account` (`social_account_id`),
  KEY `fk_content_feed` (`feed_id`),
  KEY `fk_content_site` (`site_id`),
  KEY `title` (`title`),
  KEY `status` (`status`),
  KEY `type` (`type`),
  KEY `needs_review` (`needs_review`),
  KEY `compliance_status` (`compliance_status`),
  KEY `risk_score` (`risk_score`),
  KEY `purpose` (`purpose`),
  KEY `extraction_status_idx` (`extraction_status`),
  KEY `client_id` (`client_id`),
  KEY `is_flagged_idx` (`is_flagged`),
  KEY `purpose_idx` (`purpose`),
  FULLTEXT KEY `content_index` (`title`,`body`),
  CONSTRAINT `content_ibfk_1` FOREIGN KEY (`client_id`) REFERENCES `client` (`id`),
  CONSTRAINT `fk_content_content` FOREIGN KEY (`parent_id`) REFERENCES `content` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_content_feed` FOREIGN KEY (`feed_id`) REFERENCES `feed` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_content_site` FOREIGN KEY (`site_id`) REFERENCES `site` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_content_social_account` FOREIGN KEY (`social_account_id`) REFERENCES `social_account` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `fk_content_target_social_account` FOREIGN KEY (`social_account_id`) REFERENCES `social_account` (`id`),
  CONSTRAINT `fk_content_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=247236 DEFAULT CHARSET=utf8
EN

回答 3

Database Administration用户

发布于 2018-03-07 08:00:08

在update语句中,MySQL必须计算每一行的“date_sub(创建,间隔30天)”,并将其与compliance_overridden_date进行比较。在select中,它只需要计算一次date_sub(现在(),间隔30天)。WHER-子句不允许MySQL使用索引来选择要修改的行。由于必须读取所有行,所以最好是扫描表,而不是在索引和数据之间跳过。我对解释中的“初等”没有任何解释。你猜的比我的好。

票数 2
EN

Database Administration用户

发布于 2018-03-07 08:29:30

此查询不以任何方式利用主键。检查的行数(大约160 K行)显示了这一点。因此,您认为您的UPDATE什么都不做的假设是不正确的:它检查了几行。

您的选择速度更快的原因非常清楚。该表达式在查询执行开始时计算一次:

代码语言:javascript
复制
DATE_SUB(NOW(), INTERVAL 30 DAY) 

但这是每一行的计算机(也是此查询不能使用索引的原因):

代码语言:javascript
复制
DATE_SUB(created, INTERVAL 30 DAY);

为什么EXPAIN会显示PRIMARY?我没有把握。但从技术上讲,每当您不使用辅助索引时,您总是使用主键--因为数据存储在主键中,只是没有按特定的顺序存储。

票数 1
EN

Database Administration用户

发布于 2018-03-09 17:12:02

代码语言:javascript
复制
INDEX(compliance_overridden, compliance_overridden_date)

显示使这两个查询都更快。

更好的方法是去掉标记(覆盖),并在日期中简单地使用NULL,这意味着它没有被“重写”。然后就有了

代码语言:javascript
复制
INDEX(compliance_overridden_date)
票数 0
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/199555

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档