我怎样才能使这个基本的 MySQL SELECT 查询在 10 亿行上更快?
How can I make this basic MySQL SELECT query faster on 1 billion rows?
我有一个 100GB 的大型网站内容数据集,大约有 10 亿行,我已将其编入索引 MySQL 8 table.
CREATE TABLE `inner_pages_content` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`page_id` INT(10) UNSIGNED NULL DEFAULT NULL,
`page_word` VARCHAR(50) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci',
`word_source` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
`word_frequency` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `FK_inner_pages_content_inner_pages` (`page_id`) USING BTREE,
INDEX `page_word` (`page_word`) USING BTREE,
CONSTRAINT `FK_inner_pages_content_inner_pages` FOREIGN KEY (`page_id`) REFERENCES `rocket_test`.`inner_pages` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1629374935
然后我 运行 查询与此类似的查询,以针对特定关键字建立特定页面的相关性分数。
SELECT page_id, word_source, word_frequency FROM inner_pages_content WHERE page_word IN
('docker', 'software development', 'linux', 'microsoft', 'computer software');
除了慢得令人痛苦之外,一切都运行良好。我发现的一个解决方案是将所有内容都移到 GCP 的 BigQuery 中,但在我永久地追求这条路线并注销 CloudSQL/MySQL 之前,我想看看是否有什么我可以做的来保持我的解决方案使用 CloudSQL/MySQL.
在我的 SSD 本地和具有 500GB SSD 的 CloudSQL 上,这些查询都需要 120-200 秒才能完成。
我认为一个问题(很有可能我错了!)是我没有将整个 table 放在本地内存或 CloudSQL 中,因为 100GB 内存的成本所以它总是拉磁盘的结果。
有趣的是,当我计算 (*) 匹配结果而不是 SELECT 时,速度非常快。通常不到 0.5 秒。
我能做些什么来加快查询速度吗?
附加信息
您没有索引/查询问题(因为 count(*) 时间很快。
这是IO/网络问题,所以你可以尝试将选定的字段添加到索引中以将数据放入内存中:
https://mariadb.com/kb/en/building-the-best-index-for-a-given-select/
部分:“覆盖”索引
create index page_word on inner_pages_content (page_word , page_id, word_source, word_frequency)
我有一个 100GB 的大型网站内容数据集,大约有 10 亿行,我已将其编入索引 MySQL 8 table.
CREATE TABLE `inner_pages_content` (
`id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`page_id` INT(10) UNSIGNED NULL DEFAULT NULL,
`page_word` VARCHAR(50) NULL DEFAULT NULL COLLATE 'latin1_swedish_ci',
`word_source` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
`word_frequency` TINYINT(3) UNSIGNED NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE,
INDEX `FK_inner_pages_content_inner_pages` (`page_id`) USING BTREE,
INDEX `page_word` (`page_word`) USING BTREE,
CONSTRAINT `FK_inner_pages_content_inner_pages` FOREIGN KEY (`page_id`) REFERENCES `rocket_test`.`inner_pages` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1629374935
然后我 运行 查询与此类似的查询,以针对特定关键字建立特定页面的相关性分数。
SELECT page_id, word_source, word_frequency FROM inner_pages_content WHERE page_word IN
('docker', 'software development', 'linux', 'microsoft', 'computer software');
除了慢得令人痛苦之外,一切都运行良好。我发现的一个解决方案是将所有内容都移到 GCP 的 BigQuery 中,但在我永久地追求这条路线并注销 CloudSQL/MySQL 之前,我想看看是否有什么我可以做的来保持我的解决方案使用 CloudSQL/MySQL.
在我的 SSD 本地和具有 500GB SSD 的 CloudSQL 上,这些查询都需要 120-200 秒才能完成。
我认为一个问题(很有可能我错了!)是我没有将整个 table 放在本地内存或 CloudSQL 中,因为 100GB 内存的成本所以它总是拉磁盘的结果。
有趣的是,当我计算 (*) 匹配结果而不是 SELECT 时,速度非常快。通常不到 0.5 秒。
我能做些什么来加快查询速度吗?
附加信息
您没有索引/查询问题(因为 count(*) 时间很快。 这是IO/网络问题,所以你可以尝试将选定的字段添加到索引中以将数据放入内存中:
https://mariadb.com/kb/en/building-the-best-index-for-a-given-select/
部分:“覆盖”索引
create index page_word on inner_pages_content (page_word , page_id, word_source, word_frequency)