Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.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,所以,我已经尝试了我能想到的一切,但无法在我的本地服务器上在不到3秒钟的时间内完成此查询。我知道这个问题与或引用所有者id和个人id有关。如果我运行其中一个或另一个,它会立即发生,但与OR一起运行,我似乎无法使其工作-我试图重写代码,但应用程序的设计方式并不容易。有没有一种方法我可以称之为等价物,或者不会花这么长时间?以下是sql: SELECT event_types.name as event_type_name,event_types.id as id, count(events.id)

所以,我已经尝试了我能想到的一切,但无法在我的本地服务器上在不到3秒钟的时间内完成此查询。我知道这个问题与或引用所有者id和个人id有关。如果我运行其中一个或另一个,它会立即发生,但与OR一起运行,我似乎无法使其工作-我试图重写代码,但应用程序的设计方式并不容易。有没有一种方法我可以称之为等价物,或者不会花这么长时间?以下是sql:

SELECT event_types.name as event_type_name,event_types.id as id, count(events.id) as 
count,sum(events.estimated_duration) as time_sum FROM events,event_types 
WHERE event_types.id = events.event_type_id AND events.event_type_id != '4' 
AND ( events.status!='cancelled') 
AND events.event_type_id != 64 
AND ( events.owner_id = 161 OR events.person_id = 161 ) 
GROUP BY event_types.name 
ORDER BY event_types.name DESC;
下面是解释汤,尽管我猜这是不必要的,因为可能有更好的方法来组织它,或者说这是显而易见的:

非常感谢!克里斯

+----+-------------+-------------+-------+---------------------------------------------------------------------------------------------------------+-------------------------------+---------+-------------------------------------+------+----------------------------------------------+
| id | select_type | table       | type  | possible_keys                                                                                           | key                           | key_len | ref                                 | rows | Extra                                        |
+----+-------------+-------------+-------+---------------------------------------------------------------------------------------------------------+-------------------------------+--
|  1 | SIMPLE      | event_types | range | PRIMARY                                                                                                 | PRIMARY                       | 4       | NULL                                |   78 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | events      | ref   | index_events_on_status,index_events_on_event_type_id,index_events_on_person_id,index_events_on_owner_id | index_events_on_event_type_id | 5       | thenumber_production.event_types.id |  907 | Using where                                  |
+----+-------------+-------------+-------+---------------------------------------------------------------------------------------------------------+-------------------------------+---------+-------------------------------------+------+----------------------------------------------+

查询将是一个问题。分解出永远不会执行的条件的正常解决方案是使用UNION ALL,即:

SELECT *
FROM a
WHERE field1 = 1 OR field2 = 2
致:

只要你不买或不介意复制品,这些作品就行。如果您有重复项并且需要将它们排除,您可以使用联合来代替,但它会进行隐式的不同聚合,因此性能会差得多

您还需要对结果进行排序,这也是一个问题

在这种情况下,您最好的方法是更改数据模型,这样它就可以编写性能查询,也就是说,您根本不需要使用OR


一个问题:事件的所有者id和人员id是否可能相同?

使用两个子查询,每个子查询执行两个或路径中的一个,然后合并这些子查询以在顶级select中汇总总数,怎么样

类似于:这里的语法并不精确,因为我是从内存开始的:

从中选择bname、id、sumid、sumtime\u sum 选择具有所有者id的大查询 联合选择。。。带有person_id的大查询可以尝试:

   SELECT event_types.name AS event_type_name, event_types.id AS id,
          COUNT(events.id) AS count, SUM(events.estimated_duration) AS time_sum
     FROM events
     JOIN event_types ON event_types.id = event.event_type_id
    WHERE events.event_type_id <> 4
      AND events.status <> 'cancelled'
      AND events.event_type_id <> 64 
      AND ( events.owner_id = 161 OR events.person_id = 161 ) 
 GROUP BY event_types.id 
 ORDER BY event_types.name DESC;
以下是一些提示:

使用而不是= 对id使用int值4,而不是字符串“4”
这就是我要尝试的

我会确保“所有者id”和“个人id”上都有唯一的密钥:

alter table events add unique (person_id, id), add unique (owner_id, id);
您还应定期运行以下程序:

analyze table events;
试试看

另一种选择是尝试将查询的错误部分移动到连接谓词中

SELECT event_types.name as event_type_name,event_types.id as id, count(events.id) as 
count,sum(events.estimated_duration) as time_sum FROM events,event_types
JOIN event_types on event_types.id = events.event_type_id
AND ( events.owner_id = 161 OR events.person_id = 161 )
WHERE events.event_type_id != '4' 
AND ( events.status!='cancelled') 
AND events.event_type_id != 64 
GROUP BY event_types.name 
ORDER BY event_types.name DESC;

请注意,我没有尝试过这些,这一切都是在我的头顶上。但这正是我首先要尝试的。

尝试在两个查询中使用联合将其拆分以加入结果集,一个使用events.owner\u id=161,另一个使用events.person\u id=161


使用filesort和使用temporary也是一个非常糟糕的标志,您可能应该在事件类型.名称上添加索引。

事件和事件类型上有哪些索引?同意,在所有相关表上显示CREATE TABLE的输出在这里非常有用。是的,它们可能是相同的-尽管这并不常见。听起来是时候深入挖掘了,并开始重构数据模型了。出于好奇,union是否都能与GROUPBY一起工作?union基本上只是连接查询结果,因此您可以按每个片段分组,甚至可以按一个而不是另一个进行分组。列的数量和类型必须匹配。为什么与!=?只是想澄清一下,还有!=在mysql和大多数其他类型的sql中,它们在语义上是相同的,因此不会给您带来性能上的好处。但是,将“4”改为仅4将提高性能,因为否则mysql必须在每次比较时进行转换,更重要的是,它不能在必须进行值转换时使用索引。
SELECT event_types.name as event_type_name,event_types.id as id, count(events.id) as 
count,sum(events.estimated_duration) as time_sum FROM events,event_types
JOIN event_types on event_types.id = events.event_type_id
AND ( events.owner_id = 161 OR events.person_id = 161 )
WHERE events.event_type_id != '4' 
AND ( events.status!='cancelled') 
AND events.event_type_id != 64 
GROUP BY event_types.name 
ORDER BY event_types.name DESC;