尽管存在索引,但对大型 SQL table 的排序查询速度很慢

Sorted queries on a large SQL table are slow despite an index exists

我有一个非常大的 SQL Table(超过 3 mio 行)comment_field_data。

    CREATE TABLE `comment_field_data` (
  `cid` int(10) unsigned NOT NULL,
  `comment_type` varchar(32) CHARACTER SET ascii NOT NULL COMMENT 'The ID of the target entity.',
  `langcode` varchar(12) CHARACTER SET ascii NOT NULL,
  `status` tinyint(4) NOT NULL,
  `uid` int(10) unsigned NOT NULL COMMENT 'The ID of the target entity.',
  `pid` int(10) unsigned DEFAULT NULL COMMENT 'The ID of the target entity.',
  `entity_id` int(10) unsigned DEFAULT NULL COMMENT 'The ID of the target entity.',
  `subject` varchar(64) DEFAULT NULL,
  `name` varchar(60) DEFAULT NULL,
  `mail` varchar(254) DEFAULT NULL,
  `homepage` varchar(255) DEFAULT NULL,
  `hostname` varchar(128) DEFAULT NULL,
  `created` int(11) NOT NULL,
  `changed` int(11) DEFAULT NULL,
  `thread` varchar(255) NOT NULL,
  `entity_type` varchar(32) CHARACTER SET ascii NOT NULL,
  `field_name` varchar(32) CHARACTER SET ascii NOT NULL,
  `default_langcode` tinyint(4) NOT NULL,
  PRIMARY KEY (`cid`,`langcode`),
  KEY `comment__id__default_langcode__langcode` (`cid`,`default_langcode`,`langcode`),
  KEY `comment_field__comment_type__target_id` (`comment_type`),
  KEY `comment_field__uid__target_id` (`uid`),
  KEY `comment_field__created` (`created`),
  KEY `comment__status_comment_type` (`status`,`comment_type`,`cid`),
  KEY `comment__status_pid` (`pid`,`status`),
  KEY `comment__num_new` (`entity_id`,`entity_type`,`comment_type`,`status`,`created`,`cid`,`thread`(191)),
  KEY `comment__entity_langcode` (`entity_id`,`entity_type`,`comment_type`,`default_langcode`)
)

类似

的查询
SELECT entity_id FROM comment_field_data ORDER BY created LIMIT 300

表现很差(几秒钟)- 并且

EXPLAIN SELECT entity_id FROM comment_field_data ORDER BY created LIMIT 300;
+------+-------------+--------------------+-------+---------------+------------------+---------+------+---------+-----------------------------+
| id   | select_type | table              | type  | possible_keys | key              | key_len | ref  | rows    | Extra                       |
+------+-------------+--------------------+-------+---------------+------------------+---------+------+---------+-----------------------------+
|    1 | SIMPLE      | comment_field_data | index | NULL          | comment__num_new | 848     | NULL | 3384043 | Using index; Using filesort |
+------+-------------+--------------------+-------+---------------+------------------+---------+------+---------+-----------------------------+
     

表明尽管创建的列已有索引,但仍使用了文件排序。我根本不是 SQL 专家,我不知道可以做些什么来改善这种行为。有人可以帮忙吗?

您应该尝试更改索引键:

ALTER TABLE comment_field_data
  DROP KEY `comment_field__created`, 
  ADD KEY `comment_field__created` (`created`, `entity_id`) ;

为了“鼓励”MariaDB 使用这个新索引,您可以像这样更改您的查询:

SELECT entity_id 
FROM comment_field_data 
WHERE created > '1970-01-01'
AND entity_id > 0
ORDER BY created LIMIT 300

希望这会有所帮助

这种技术被命名为索引覆盖,这意味着索引结构包含查询中调用的所有列。

使用这个索引,为了执行你的查询,MariaDB 将不必做额外的I/Os读取主键中包含的数据层。