如何加快select count(*)用group by? 它太慢并且经常使用。 我用很大的麻烦select count(*),并group by具有300多万行的表。
select count(*)
group by
select object_title,count(*) as hot_num from relations where relation_title='XXXX' group by object_title
Relation_title , object_title 为varchar。 其中Relation_title =’XXXX’ ,返回超过1,000,000行,导致 object_title 上的索引 无法正常工作。
为了提高难度,我尝试了以下几种方法:
(更轻松) - 确保您具有正确的覆盖指数
CREATE INDEX ix_temp ON relations (relation_title, object_title);
在给定现有架构的情况下,这应该使性能最大化,因为(除非您的mySQL优化器版本真的很笨!)它将最小化满足查询所需的I / O数量(与索引相反的情况不同,即整个索引必须进行扫描),它会覆盖查询,因此您无需触摸聚簇索引。
(稍微难一点)-确保您的varchar字段尽可能小
MySQL上使用varchar索引的性能挑战之一是,在处理查询时,字段的完整声明大小将被拉入RAM。因此,如果您具有varchar(256),但仅使用4个字符,则在处理查询时,您仍然需要支付256字节的RAM使用量。哎哟! 因此,如果您可以轻松缩小varchar限制,则可以加快查询速度。
(更难)-标准化
您有30%的具有单个字符串值的行显然可以正常化到另一个表中,因此您不会将字符串重复数百万次。考虑将其标准化为三个表,并使用整数ID将它们联接。
在某些情况下,您可以在幕后进行归一化,并使用与当前表名称匹配的视图隐藏归一化…然后,您只需要使INSERT / UPDATE / DELETE查询知道该归一化,但可以不理会SELECTs 。
(最困难)-散列字符串列并为哈希索引
如果规范化意味着更改太多代码,但是您可以稍微更改架构,则可能要考虑为字符串列创建128位哈希(使用MD5函数)。在这种情况下(与规范化不同),您不必更改所有查询,而只需更改INSERT和某些SELECT。无论如何,您将需要对字符串字段进行哈希处理,然后在哈希表上创建索引,例如
CREATE INDEX ix_temp ON relations (relation_title_hash, object_title_hash);
请注意,您将需要使用SELECT来确保通过哈希索引进行计算,而不要拉入聚集索引(需要解析object_title的实际文本值才能满足查询)。
另外,如果relationship_title具有较小的varchar大小,但对象标题具有较大的大小,则可能仅散列object_title并在上创建索引(relation_title, object_title_hash)。
(relation_title, object_title_hash)
请注意,仅当这些字段中的一个或两个相对于哈希值的大小很长时,此解决方案才有用。
还要注意,由于小写字符串的哈希值与大写字符串的哈希值不同,因此哈希值会引起有趣的区分大小写/排序规则的影响。因此,您需要确保对字符串进行规范化之后再对它们进行哈希处理- 换句话说,如果您在不区分大小写的数据库中,则仅对小写字母进行哈希处理。您还可能需要从头或尾开始修剪空格,具体取决于数据库处理前导/尾随空格的方式。