Update: where子句是相同的。结果概述如下。
以下查询在0.1s内运行,并返回0结果。
SELECT id from content WHERE compliance_overridden = 1 AND compliance_overridden_date < DATE_SUB(NOW(), INTERVAL 30 DAY);因此,我希望在同一时间内返回以下查询(因为它实际上不需要更新任何内容)。
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创建表内容;
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发布于 2018-03-07 08:00:08
在update语句中,MySQL必须计算每一行的“date_sub(创建,间隔30天)”,并将其与compliance_overridden_date进行比较。在select中,它只需要计算一次date_sub(现在(),间隔30天)。WHER-子句不允许MySQL使用索引来选择要修改的行。由于必须读取所有行,所以最好是扫描表,而不是在索引和数据之间跳过。我对解释中的“初等”没有任何解释。你猜的比我的好。
发布于 2018-03-07 08:29:30
此查询不以任何方式利用主键。检查的行数(大约160 K行)显示了这一点。因此,您认为您的UPDATE什么都不做的假设是不正确的:它检查了几行。
您的选择速度更快的原因非常清楚。该表达式在查询执行开始时计算一次:
DATE_SUB(NOW(), INTERVAL 30 DAY) 但这是每一行的计算机(也是此查询不能使用索引的原因):
DATE_SUB(created, INTERVAL 30 DAY);为什么EXPAIN会显示PRIMARY?我没有把握。但从技术上讲,每当您不使用辅助索引时,您总是使用主键--因为数据存储在主键中,只是没有按特定的顺序存储。
发布于 2018-03-09 17:12:02
INDEX(compliance_overridden, compliance_overridden_date)显示使这两个查询都更快。
更好的方法是去掉标记(覆盖),并在日期中简单地使用NULL,这意味着它没有被“重写”。然后就有了
INDEX(compliance_overridden_date)https://dba.stackexchange.com/questions/199555
复制相似问题