Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql:优化派生表的计数查询_Mysql_Performance - Fatal编程技术网

Mysql:优化派生表的计数查询

Mysql:优化派生表的计数查询,mysql,performance,Mysql,Performance,为了分页的目的,我正在尝试对派生表进行计数查询。查询如下所示: SELECT assignment_completions.id as id, assignment_completions.first_name, assignment_completions.last_name, groups.name FROM assignment_completions LEFT JOIN groups_users ON assignmen

为了分页的目的,我正在尝试对派生表进行计数查询。查询如下所示:

SELECT 
    assignment_completions.id as id,
    assignment_completions.first_name,
    assignment_completions.last_name,
    groups.name

FROM
    assignment_completions
        LEFT JOIN
    groups_users ON assignment_completions.user_id = groups_users.user_id
        LEFT JOIN
    groups ON groups_users.group_id = groups.id
WHERE
    assignment_completions.handler = 'course'
GROUP BY assignment_completions.id
SELECT COUNT(*) FROM (...) AS assignment_count
count查询只是像这样包装了上述查询:

SELECT 
    assignment_completions.id as id,
    assignment_completions.first_name,
    assignment_completions.last_name,
    groups.name

FROM
    assignment_completions
        LEFT JOIN
    groups_users ON assignment_completions.user_id = groups_users.user_id
        LEFT JOIN
    groups ON groups_users.group_id = groups.id
WHERE
    assignment_completions.handler = 'course'
GROUP BY assignment_completions.id
SELECT COUNT(*) FROM (...) AS assignment_count
没有计数的查询将在.005秒内执行。 带有计数的查询将在1.5秒内执行

我尝试了以下方法,但没有成功:

1) 使用索引列(此处没有性能增益):

2) 我尝试过使用
SQL\u CALC\u FOUND\u ROWS
,但实际上速度稍慢(2秒左右)

详细信息:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: assignment_completions
         type: index
possible_keys: PRIMARY,index_assignment_completions_on_first_name,index_assignment_completions_on_last_name,index_assignment_completions_on_user_id
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 199088
     filtered: 100.00
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.assignment_completions.user_id
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 3. row ***************************
           id: 1
  select_type: SIMPLE
        table: groups_users
         type: ref
possible_keys: index_groups_users_on_user_id
          key: index_groups_users_on_user_id
      key_len: 5
          ref: lms.users.id
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 4. row ***************************
           id: 1
  select_type: SIMPLE
        table: groups
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.groups_users.group_id
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived2>
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 199088
     filtered: 100.00
        Extra: NULL
*************************** 2. row ***************************
           id: 2
  select_type: DERIVED
        table: assignment_completions
         type: index
possible_keys: PRIMARY,index_assignment_completions_on_first_name,index_assignment_completions_on_last_name,index_assignment_completions_on_user_id
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 199088
     filtered: 100.00
        Extra: Using where
*************************** 3. row ***************************
           id: 2
  select_type: DERIVED
        table: users
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.assignment_completions.user_id
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 4. row ***************************
           id: 2
  select_type: DERIVED
        table: groups_users
         type: ref
possible_keys: index_groups_users_on_user_id
          key: index_groups_users_on_user_id
      key_len: 5
          ref: lms.users.id
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 5. row ***************************
           id: 2
  select_type: DERIVED
        table: groups
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.groups_users.group_id
         rows: 1
     filtered: 100.00
        Extra: Using index
作业完成:20万行

用户:35k行

用户组:500k行

分组:1k行

表格定义

CREATE TABLE `assignment_completions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) DEFAULT NULL,
  `assignment_id` int(11) DEFAULT NULL,
  `handler` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `handler_id` int(11) DEFAULT NULL,
  `time_started` datetime DEFAULT NULL,
  `time_end` datetime DEFAULT NULL,
  `status` int(11) DEFAULT NULL,
  `application_instance_id` int(11) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `first_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `last_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `index_assignment_completions_on_first_name` (`first_name`) USING BTREE,
  KEY `index_assignment_completions_on_last_name` (`last_name`) USING BTREE,
  KEY `index_assignment_completions_on_user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=200001 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `encrypted_password` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `reset_password_token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `reset_password_sent_at` datetime DEFAULT NULL,
  `remember_created_at` datetime DEFAULT NULL,
  `sign_in_count` int(11) NOT NULL DEFAULT '0',
  `current_sign_in_at` datetime DEFAULT NULL,
  `last_sign_in_at` datetime DEFAULT NULL,
  `current_sign_in_ip` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `last_sign_in_ip` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `application_instance_id` int(11) DEFAULT NULL,
  `username` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `first_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `last_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `status` int(11) DEFAULT NULL,
  `group_list_cache` text COLLATE utf8_unicode_ci,
  PRIMARY KEY (`id`),
  UNIQUE KEY `index_users_on_reset_password_token` (`reset_password_token`) USING BTREE,
  UNIQUE KEY `index_users_on_username_and_application_instance_id` (`username`,`application_instance_id`) USING BTREE,
  KEY `index_users_on_application_instance_id` (`application_instance_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=30006 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

CREATE TABLE `groups_users` (
  `group_id` int(11) DEFAULT NULL,
  `user_id` int(11) DEFAULT NULL,
  UNIQUE KEY `index_groups_users_on_group_id_and_user_id` (`group_id`,`user_id`) USING BTREE,
  KEY `index_groups_users_on_group_id` (`group_id`) USING BTREE,
  KEY `index_groups_users_on_user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

CREATE TABLE `groups` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `application_instance_id` int(11) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `description` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `group_type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1045 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
解释查询:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: assignment_completions
         type: index
possible_keys: PRIMARY,index_assignment_completions_on_first_name,index_assignment_completions_on_last_name,index_assignment_completions_on_user_id
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 199088
     filtered: 100.00
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.assignment_completions.user_id
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 3. row ***************************
           id: 1
  select_type: SIMPLE
        table: groups_users
         type: ref
possible_keys: index_groups_users_on_user_id
          key: index_groups_users_on_user_id
      key_len: 5
          ref: lms.users.id
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 4. row ***************************
           id: 1
  select_type: SIMPLE
        table: groups
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.groups_users.group_id
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived2>
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 199088
     filtered: 100.00
        Extra: NULL
*************************** 2. row ***************************
           id: 2
  select_type: DERIVED
        table: assignment_completions
         type: index
possible_keys: PRIMARY,index_assignment_completions_on_first_name,index_assignment_completions_on_last_name,index_assignment_completions_on_user_id
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 199088
     filtered: 100.00
        Extra: Using where
*************************** 3. row ***************************
           id: 2
  select_type: DERIVED
        table: users
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.assignment_completions.user_id
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 4. row ***************************
           id: 2
  select_type: DERIVED
        table: groups_users
         type: ref
possible_keys: index_groups_users_on_user_id
          key: index_groups_users_on_user_id
      key_len: 5
          ref: lms.users.id
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 5. row ***************************
           id: 2
  select_type: DERIVED
        table: groups
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.groups_users.group_id
         rows: 1
     filtered: 100.00
        Extra: Using index
计数查询解释:

*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: assignment_completions
         type: index
possible_keys: PRIMARY,index_assignment_completions_on_first_name,index_assignment_completions_on_last_name,index_assignment_completions_on_user_id
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 199088
     filtered: 100.00
        Extra: Using where
*************************** 2. row ***************************
           id: 1
  select_type: SIMPLE
        table: users
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.assignment_completions.user_id
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 3. row ***************************
           id: 1
  select_type: SIMPLE
        table: groups_users
         type: ref
possible_keys: index_groups_users_on_user_id
          key: index_groups_users_on_user_id
      key_len: 5
          ref: lms.users.id
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 4. row ***************************
           id: 1
  select_type: SIMPLE
        table: groups
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.groups_users.group_id
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: <derived2>
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 199088
     filtered: 100.00
        Extra: NULL
*************************** 2. row ***************************
           id: 2
  select_type: DERIVED
        table: assignment_completions
         type: index
possible_keys: PRIMARY,index_assignment_completions_on_first_name,index_assignment_completions_on_last_name,index_assignment_completions_on_user_id
          key: PRIMARY
      key_len: 4
          ref: NULL
         rows: 199088
     filtered: 100.00
        Extra: Using where
*************************** 3. row ***************************
           id: 2
  select_type: DERIVED
        table: users
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.assignment_completions.user_id
         rows: 1
     filtered: 100.00
        Extra: Using index
*************************** 4. row ***************************
           id: 2
  select_type: DERIVED
        table: groups_users
         type: ref
possible_keys: index_groups_users_on_user_id
          key: index_groups_users_on_user_id
      key_len: 5
          ref: lms.users.id
         rows: 1
     filtered: 100.00
        Extra: NULL
*************************** 5. row ***************************
           id: 2
  select_type: DERIVED
        table: groups
         type: eq_ref
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 4
          ref: lms.groups_users.group_id
         rows: 1
     filtered: 100.00
        Extra: Using index
因此,有必要与groups表连接。

我相信COUNT(DISTINCT…)aggregate函数将解决这个问题:

SELECT COUNT(DISTINCT assignment_completions.id) AS assignment_count
FROM assignment_completions
    LEFT JOIN users ON assignment_completions.user_id = users.id
    LEFT JOIN groups_users ON users.id = groups_users.user_id
    LEFT JOIN groups ON groups_users.group_id = groups.id
WHERE assignment_completions.handler = 'course';
为了加快速度,您可以将其与其他查询分开运行,如下所示:

SELECT COUNT(DISTINCT id) AS assignment_count
FROM assignment_completions
WHERE assignment_completions.handler = 'course';

由于您最终通过赋值\u completions.id对组进行了分组,并且由于此表与所有其他表进行了左联接,因此所需的查询相当于:

SELECT COUNT(DISTINCT id) FROM assignment_completions;
最后,
id
可能是主键(因此是唯一的),因此您只需要:

SELECT COUNT(id) FROM assignment_completions;


由于您确实需要
表对其进行筛选,因此不需要
左连接
。也许乐观主义者自己就意识到了这一点,但如果没有,用常规的
[internal]连接替换所有
左连接
,我将在数据上有以下覆盖索引,这样引擎就不必返回原始数据页。另外,由于从用户到组用户的唯一目的是,但是组用户无论如何都是基于用户id的,因此从分配完成直接到组用户表

table                   index
assignment_completions  ( handler, id, user_id, first_name, last_name )
groups_users            ( user_id, group_id )
groups                  ( id, name )

SELECT STRAIGHT_JOIN
      assignment_completions.id as id,
      assignment_completions.first_name,
      assignment_completions.last_name,
      groups.name
   FROM
      assignment_completions
         LEFT JOIN groups_users 
            ON assignment_completions.user_id = groups_users.user_id
            LEFT JOIN groups 
               ON groups_users.group_id = groups.id
   WHERE
      assignment_completions.handler = 'course'
   GROUP BY 
      assignment_completions.id
@奥鲁克德,我又看了看桌子的结构。真的,你会期望一个名字(第一个/最后一个)超过20-25个字符吗?另外,处理程序字段是否为255个字符?真正地如果这导致数据页过度膨胀,这是否是延迟问题的一部分?在用户的表中也是如此。此外,如果任务完成的名字/姓氏是完成任务的用户的名字/姓氏,那么从长远来看,只将用户的ID存储到表中会容易得多,并缩短任务完成时的磁盘需求。是的,是一个额外的连接,但由于它将基于一个“ID”列,因此速度会很快,特别是如果用户的表是(ID、first\u name、last\u name)上的覆盖索引,但肯定会缩小这些列的大小。类似于组“名称”列。因为我不知道实际索引是如何准备的,如果每个字段分配255个索引,可能会影响索引性能

在重新审视我自己的评论之后。您似乎有一个要查找的处理程序查找表(通过引用handler\u id列)。我会在assignment_completions表上将索引从(handler…)更改为(handler_id…),并删除handler列,因为与单个查找表id指针相比,超过200k行的重复将减少要浏览的页面数量。同样,在分配完成表中保存“userID”与完整的姓/名。这就迫使200k条记录有3列,每列最多255个字符(到目前为止,显然还会增加)

为了处理SELECT COUNT(*)FROM t语句,InnoDB扫描表的索引,如果索引不完全在缓冲池中,这需要一些时间。如果您的表不经常更改,那么使用MySQL查询缓存是一个很好的解决方案。快速计数

您还可以强制InnoDB使用索引:

  SELECT COUNT(id) FROM assignment_completions USE INDEX (PRIMARY);
除此之外,我看到您使用了许多索引,这将减慢查询速度

请尝试仅使用您将依赖的id上的索引

Innodb没有缓存行计数。因此,使用Innodb表时,count(*)without where子句的速度很慢

您可以尝试以下方法:

    CREATE TEMPORARY TABLE `tmp_stuff` SELECT 
        assignment_completions.id as id,
        assignment_completions.first_name,
        assignment_completions.last_name,
        groups.name

    FROM
        assignment_completions
            LEFT JOIN
        groups_users ON assignment_completions.user_id = groups_users.user_id
            LEFT JOIN
        groups ON groups_users.group_id = groups.id
    WHERE
        assignment_completions.handler = 'course'
    GROUP BY assignment_completions.id
然后这个:

    SELECT count(*) FROM `tmp_stuff`
如果您的计数(*)需要更复杂,您可以始终向临时表添加必要的索引


它不会变得非常快,但是当复杂的查询开始变慢时,即使有正确的索引,临时表也会挽救您的生命。

您能添加您的表定义和
解释选择的输出吗?您有10万组(100万组,或仅1千组)。至于计数,你想得到什么计数。打字错误!1k组。我正在努力计算总的结果。对于常规查询,我对其进行了限制。然后我再次执行它,不受限制地获得分页的总结果。这在正常情况下效果很好,与will paginate gem for rails使用的技术相同。@orourkedd Hm。。。目前没有任何好主意。也许可以使用mysql探查器来找出究竟需要比预期更长的时间(请阅读此处的工作原理:)。探查器说瓶颈在于“发送数据”,这意味着“您的查询速度很慢”。只是尝试了一下,它并没有提供任何性能提升。顺便说一句,您的初始查询有点失败。在<代码> >选择< /代码>部分中,您拥有<>代码>组。对于一个给定的
赋值\u completions.id
,可能存在多个
组。name
。您将在结果集中得到的是未定义的。问题是,此查询有时会添加一个附加的“where”子句,如:
groups.name,如“%abc%”
如果在
group
表上添加条件,则不必使用
左连接。使用常规的
内部联接
。请注意,没有一个用于所有查询。如果您关心的是性能,那么您通常需要制定一个特定的