MySQL GROUP BY 不必要地使用临时?
MySQL GROUP BY with Using Temporary unnecessarily?
我正在尝试优化查询。使用 EXPLAIN
告诉我它是 Using temporary
。考虑到 table(20m+ 记录)的大小,这确实效率低下。查看 MySQL 文档 Internal Temporary Tables 我没有看到任何暗示在我的查询中需要临时 table 的内容。我还尝试将 ORDER BY 设置为与 GROUP BY 相同,但仍然说 Using Temporary and query takes forever to 运行。我正在使用 MySQL 5.7.
有没有办法避免对这个查询使用临时 table:
SELECT url,count(*) as sum
FROM `digital_pageviews` as `dp`
WHERE `publisher_uuid` = '8b83120e-3e19-4c34-8556-7b710bd7b812'
GROUP BY url
ORDER BY NULL;
这是我的 table 架构:
create table digital_pageviews
(
id int unsigned auto_increment
primary key,
visitor_uuid char(36) null,
publisher_uuid char(36) default '' not null,
property_uuid char(36) null,
ip_address char(15) not null,
referrer text null,
url_delete text null,
url varchar(255) null,
url_tmp varchar(255) null,
meta text null,
date_created timestamp not null,
date_updated timestamp null
)
collate = utf8_unicode_ci;
create index digital_pageviews_url_index
on digital_pageviews (url);
create index ndx_date_created
on digital_pageviews (date_created);
create index ndx_property_uuid
on digital_pageviews (property_uuid);
create index ndx_publisher_uuid
on digital_pageviews (publisher_uuid);
create index ndx_visitor_uuid_page
on digital_pageviews (visitor_uuid);
它需要临时 table 的原因是它不能同时按 publisher_uuid
过滤和对没有索引的列进行排序来同时执行这两项操作。第一步是按 publisher_uuid
过滤,因此它使用 publisher_uuid
.
上的索引
但是,接下来它必须对记录进行分组和排序,这将需要一个临时的 table,因为它不能使用可以执行此操作的索引。它不能使用索引的原因是它已经使用了 publisher_uuid
,它没有在 url
字段上建立索引来进行分组或在您排序的字段上。
要过滤 publisher_uuid = '8b83120e-3e19-4c34-8556-7b710bd7b812'
、按 url
分组并按 url
排序,请按以下顺序使用这些字段创建索引:
- publisher_uuid
- url
create index ndx_publisher_uuid
on digital_pageviews (publisher_uuid, url);
我正在尝试优化查询。使用 EXPLAIN
告诉我它是 Using temporary
。考虑到 table(20m+ 记录)的大小,这确实效率低下。查看 MySQL 文档 Internal Temporary Tables 我没有看到任何暗示在我的查询中需要临时 table 的内容。我还尝试将 ORDER BY 设置为与 GROUP BY 相同,但仍然说 Using Temporary and query takes forever to 运行。我正在使用 MySQL 5.7.
有没有办法避免对这个查询使用临时 table:
SELECT url,count(*) as sum
FROM `digital_pageviews` as `dp`
WHERE `publisher_uuid` = '8b83120e-3e19-4c34-8556-7b710bd7b812'
GROUP BY url
ORDER BY NULL;
这是我的 table 架构:
create table digital_pageviews
(
id int unsigned auto_increment
primary key,
visitor_uuid char(36) null,
publisher_uuid char(36) default '' not null,
property_uuid char(36) null,
ip_address char(15) not null,
referrer text null,
url_delete text null,
url varchar(255) null,
url_tmp varchar(255) null,
meta text null,
date_created timestamp not null,
date_updated timestamp null
)
collate = utf8_unicode_ci;
create index digital_pageviews_url_index
on digital_pageviews (url);
create index ndx_date_created
on digital_pageviews (date_created);
create index ndx_property_uuid
on digital_pageviews (property_uuid);
create index ndx_publisher_uuid
on digital_pageviews (publisher_uuid);
create index ndx_visitor_uuid_page
on digital_pageviews (visitor_uuid);
它需要临时 table 的原因是它不能同时按 publisher_uuid
过滤和对没有索引的列进行排序来同时执行这两项操作。第一步是按 publisher_uuid
过滤,因此它使用 publisher_uuid
.
但是,接下来它必须对记录进行分组和排序,这将需要一个临时的 table,因为它不能使用可以执行此操作的索引。它不能使用索引的原因是它已经使用了 publisher_uuid
,它没有在 url
字段上建立索引来进行分组或在您排序的字段上。
要过滤 publisher_uuid = '8b83120e-3e19-4c34-8556-7b710bd7b812'
、按 url
分组并按 url
排序,请按以下顺序使用这些字段创建索引:
- publisher_uuid
- url
create index ndx_publisher_uuid
on digital_pageviews (publisher_uuid, url);