我有一个非常大的MySQL InnoDB表,其结构如下:
TABLE `whois_records` (
`record_id` int(10) unsigned NOT NULL,
`domain_name` varchar(100) NOT NULL,
`tld_id` smallint(5) unsigned DEFAULT NULL,
`create_date` date DEFAULT NULL,
`update_date` date DEFAULT NULL,
`expiry_date` date DEFAULT NULL,
`query_time` datetime NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
PRIMARY KEY (`record_id`)
UNIQUE KEY `domain_time` (`domain_name`,`query_time`)
INDEX `tld_id` (`tld_id`)
此表目前有1000万行。 它存储频繁更新的域名详细信息。 因此,表中可以存在多个相同域名的记录。
TLD ID是域扩展类型的数值。
问题在于我试图计算特定顶级域名的域名总数。
我尝试了以下3个SQL查询:
SELECT COUNT(DISTINCT(domain_name)) FROM `whois_records` WHERE tld_id=159
SELECT COUNT(*) FROM `whois_records` WHERE tld_id=159 GROUP BY domain_name
SELECT COUNT(*) FROM ( SELECT 1 FROM `whois_records` WHERE tld_id=159 GROUP BY domain_name) q
所有3个都很慢,需要5到10分钟。它也耗尽了大量的CPU来完成。在TLD ID列上定义了INDEX,因此这些查询可能正在执行FULL INDEX SCAN。它仍然很慢。 TLD ID为159适用于" .com",其数量最多。所以当搜索159时,它是最慢的。对于不受欢迎的TLD,少于100个域,相同的查询大约需要0.10秒。 TLD ID 159有大约600万条记录,占整个表格的60%,包括1000万行。
有没有办法优化计算?
随着表的增长,当前查询将花费更长时间。所以,任何人都可以帮助我解决这个问题。是否需要更改表格? Plz帮忙,谢谢:)
答案 0 :(得分:2)
将索引扩展为包含domain_name
:
INDEX `tld_id` (`tld_id`, `domain_name`)
这应该使MySQL只使用索引而不是表数据来计算结果。如果两个值的组合都是唯一的,则添加一个新的唯一索引:
UNIQUE INDEX `new_index` (`tld_id`, `domain_name`)
我怀疑你能不能比这更进一步。如果仍然不够快,请考虑缓存计数器。