【发布时间】:2015-07-28 06:35:27
【问题描述】:
我有一个非常大的 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 是域扩展类型的数值。
问题是当我尝试计算特定 TLD 的域名总数时。
我尝试了以下 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。它仍然很慢。 159 的 TLD ID 用于“.com”,这是数量最多的。因此,在搜索 159 时,它是最慢的。对于域名少于 100 个的非流行 TLD,相同的查询大约需要 0.10 秒。 TLD ID 159 有大约 600 万条记录,占由 1000 万行组成的整个表的 60%。
有没有办法优化计算?
随着表的增长,当前查询将花费更长的时间。所以请任何人都可以帮助我解决这个问题的未来证明解决方案。是否需要更改表格?请帮忙,谢谢:)
【问题讨论】:
-
分享您的 my.cnf 配置文件和服务器配置(CPU、内存、驱动器类型、专用机器与否)。这一切对于为您指明正确的方向至关重要。
-
第二个问题:tld_id 可以为空吗?如果没有,请先更改方案。无效字段(可以为 NULL)显着减慢查找速度。
-
感谢您的回复。是的,对于无法识别的域扩展,tld_id 可以为 NULL。我应该删除 NULL,并将所有 NULL 更改为 0 吗?
-
是的,如果应用程序逻辑可以处理的话。但这仅仅是开始。请分享服务器配置
-
问题是基数,如果你的条件从表中返回大部分行,索引搜索或松散的索引扫描很快就会变得无用。所以你最希望的是索引扫描和如果 mysql 优化器这么认为,即使这样也可能不是一个选项。简而言之,索引的值太多而没有意义