MySQL GROUP BY与不必要的临时使用?

问题描述 投票:1回答:1

我正在尝试优化查询。使用EXPLAIN告诉我它是Using temporary。考虑到表的大小(20m +记录),这实际上是低效的。查看MySQL文档Internal Temporary Tables我没有看到任何暗示在我的查询中需要临时表的内容。我也尝试将ORDER BY设置为与GROUP BY相同,但仍然说使用临时和查询需要永远运行。我正在使用MySQL 5.7。

有没有办法避免为此查询使用临时表:

SELECT url,count(*) as sum 
FROM `digital_pageviews` as `dp` 
WHERE `publisher_uuid` = '8b83120e-3e19-4c34-8556-7b710bd7b812' 
GROUP BY url 
ORDER BY NULL;

这是我的表架构:

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);

mysql explain
1个回答
4
投票

它需要一个临时表的原因是它既不能通过publisher_uuid进行过滤,也不能对没有索引的列进行排序。第一步是通过publisher_uuid过滤,因此它使用publisher_uuid上的索引。

但是,接下来它必须分组并对记录进行排序,这将需要一个临时表,因为它不能使用将执行此操作的索引。它不能使用索引的原因是它已经使用了publisher_uuid,它没有在url字段上编入索引,无法按照您所订购的字段进行分组。

要过滤publisher_uuid = '8b83120e-3e19-4c34-8556-7b710bd7b812'url分组和url排序的位置,请按以下顺序创建包含这些字段的索引:

  • publisher_uuid
  • 网址
create index ndx_publisher_uuid
  on digital_pageviews (publisher_uuid, url);
© www.soinside.com 2019 - 2024. All rights reserved.