Mysql 我想优化这个查询,它需要很多时间来执行

Mysql 我想优化这个查询,它需要很多时间来执行,mysql,sql,performance,select,query-optimization,Mysql,Sql,Performance,Select,Query Optimization,我想优化这个需要大量时间执行的查询 SELECT DISTINCT j1.job_id, j1.job_name, j1.client_id, j1.job_status_id, j1.int_job_status_id, j1.job_type_id, j1.job_due_date, j1.job_received, c1.client_name, c1.id, j1.period, j1.notes, j1.staff_notes,

我想优化这个需要大量时间执行的查询

SELECT DISTINCT
  j1.job_id,
  j1.job_name,
  j1.client_id,
  j1.job_status_id,
  j1.int_job_status_id,
  j1.job_type_id,
  j1.job_due_date,
  j1.job_received,
  c1.client_name,
  c1.id,
  j1.period,
  j1.notes,
  j1.staff_notes,
  j1.job_genre,
  j1.job_submitted,
  j1.mas_Code,
  DATE_FORMAT(j1.job_completed_date, '%d/%m/%Y')    completedDate,
  j1.invoiceno,
  j1.is_active,
  p1.name,
  s1.job_status
FROM CLIENT c1,
  pr_practice p1,
  sub_subactivity sa,
  job_status s1,
  job j1
  LEFT JOIN task t
    ON j1.job_id = t.job_id
  LEFT JOIN task_assign ta
    ON ta.task_id = t.task_id
WHERE j1.client_id = c1.client_id
    AND c1.id = p1.id
    AND t.job_id = j1.job_id
    AND sa.sub_Code = j1.job_type_id
    AND j1.job_status_id = s1.job_status_id
    AND j1.discontinue_date IS NULL
    AND j1.job_submitted = 'Y'
    AND j1.job_status_id <> 7
    AND p1.id = c1.id
    AND (j1.job_type_id IN(8,5,6,9,19,19,7,16,17)
         AND (FIND_IN_SET(134,p1.sr_manager)
               OR FIND_IN_SET(134,p1.manager)
               OR FIND_IN_SET(134,p1.tl1)
               OR FIND_IN_SET(134,p1.tl2)
               OR FIND_IN_SET(134,p1.tl3)
               OR FIND_IN_SET(134,p1.tl4)
               OR FIND_IN_SET(134,p1.sales))
          OR ta.assignee_id IN(134))
    AND j1.is_active = 1
ORDER BY j1.job_received DESC, j1.job_id DESC
LIMIT 0,25
练习台

id int(11) | sr_manager | manager | t1 |t2 |t3 |t4 |sales varchar(255)
工作表

j1.job_id,   j1.job_name,   j1.client_id,   j1.job_status_id,   j1.int_job_status_id,  j1.job_type_id,   j1.job_due_date,   j1.job_received,  j1.period,
  j1.notes,  j1.staff_notes,  j1.job_genre,  j1.job_submitted,  j1.mas_Code etc.
任务表

task_id | id (practice id) | client_id | job_id 
任务受让人

id | task_id | assignee_id
请指教

试试这个:

SELECT DISTINCT j1.job_id, j1.job_name, j1.client_id, j1.job_status_id, 
         j1.int_job_status_id, j1.job_type_id, j1.job_due_date, j1.job_received, 
         c1.client_name, c1.id, j1.period, j1.notes, j1.staff_notes, j1.job_genre, 
         j1.job_submitted, j1.mas_Code, DATE_FORMAT(j1.job_completed_date, '%d/%m/%Y') completedDate, 
         j1.invoiceno, j1.is_active, p1.name, s1.job_status
FROM CLIENT c1, 
INNER JOIN pr_practice p1 ON c1.id = p1.id 
INNER JOIN job j1 ON j1.client_id = c1.client_id AND j1.is_active = 1
INNER JOIN sub_subactivity sa ON sa.sub_Code = j1.job_type_id
INNER JOIN job_status s1 ON j1.job_status_id = s1.job_status_id
LEFT JOIN task t ON j1.job_id = t.job_id
LEFT JOIN task_assign ta ON ta.task_id = t.task_id
WHERE j1.discontinue_date IS NULL AND j1.job_submitted = 'Y' AND 
        j1.job_status_id <> 7 AND j1.job_type_id IN (8,5,6,9,19,19,7,16,17) AND 
       FIND_IN_SET(134, CONCAT_WS(',', p1.sr_manager, p1.manager, p1.tl1, p1.tl2, p1.tl3, p1.tl4, p1.sales, ta.assignee_id))    
ORDER BY j1.job_received DESC, j1.job_id DESC
LIMIT 0,25
选择不同的j1.job\u id、j1.job\u name、j1.client\u id、j1.job\u status\u id、,
j1.int\U job\U status\U id,j1.job\U type\U id,j1.job\U due\U date,j1.job\U received,
c1.客户名称,c1.id,j1.期间,j1.注释,j1.员工注释,j1.工作类型,
j1.job_提交,j1.mas_代码,日期格式(j1.job_完成日期,%d/%m/%Y')完成日期,
j1.invoiceno,j1.is\U激活,p1.name,s1.job\U状态
来自客户c1,
c1.id=p1.id上的内部连接实践p1
j1.client\u id=c1.client\u id和j1.is\u active=1上的内部联接作业j1
sa上的内部联接子活动sa.sub子活动代码=j1.job子活动类型id
j1上的内部联接作业状态s1。作业状态\U id=s1。作业状态\U id
j1.job\u id=t.job\u id上的左连接任务t
左连接任务\u在ta上分配ta.task\u id=t.task\u id
其中,j1.contract_date为空,而j1.job_submitted='Y'和
(8,5,6,9,19,19,7,16,17)和
在集合中查找(134,CONCAT_WS(“,”,p1.sr_manager,p1.manager,p1.tl1,p1.tl2,p1.tl3,p1.tl4,p1.sales,ta.assignee_id))
按j1.job\u接收说明、j1.job\u id说明订购
限值0,25

这个问题没有确定任何表上的任何索引

SQL性能的关键在于了解优化器可以使用哪些操作,以及MySQL如何从可用操作中选择哪些操作。拥有合适的可用索引可以让MySQL能够利用这些索引来制定更高效的执行计划

由于
EXPLAIN
没有输出,我们只能猜测执行计划

对于缓慢的表现,我们最初的下意识反应是添加适当的指数。第二个想法是,当谓词包含
条件时,MySQL并不总是做出最有效的选择。LIMIT子句在处理过程中最后应用。。。MySQL将在应用限制之前,对整个resultset处理DISTINCT和ORDER BY操作。而且,在大型集合上,使用filesort的
操作可能会很昂贵

作为定义可能合适的索引的第一步:

... ON job (discontinue_date, is_active, job_submitted, job_received, job_id, job_status_id)
... ON job_status (job_status_id, job_status)
... ON pr_practice (id)
... ON sub_subactivity (sub_Code)
... ON task (job_id, task_id)
... ON task_assign (task_id, assignee_id)
... ON CLIENT (client_id, id, client_name) 
我们确实需要查看
EXPLAIN
的输出,以了解MySQL是否正在使用这些索引,并且我们需要测试性能


我们通常避免在连接操作中使用老式的逗号语法;我们更喜欢使用较新的
JOIN
关键字语法,并将JOIN谓词从
WHERE
子句重新定位到适当的ON子句。(逗号语法仍然可用并受支持,但这对于与旧SQL的兼容性非常有用。)


我们可以重新编写查询,保留与原始SQL相同的规范,但这可能不会改变执行计划,因此不会导致性能上的任何差异:

SELECT DISTINCT j1.job_id
     , j1.job_name
     , j1.client_id
     , j1.job_status_id
     , j1.int_job_status_id
     , j1.job_type_id
     , j1.job_due_date
     , j1.job_received
     , c1.client_name
     , c1.id
     , j1.period
     , j1.notes
     , j1.staff_notes
     , j1.job_genre
     , j1.job_submitted
     , j1.mas_Code
     , DATE_FORMAT(j1.job_completed_date, '%d/%m/%Y') AS completedDate
     , j1.invoiceno
     , j1.is_active
     , p1.name
     , s1.job_status
  FROM job              j1
  JOIN CLIENT           c1 ON c1.client_id     = j1.client_id
  JOIN pr_practice      p1 ON p1.id            = c1.id
  JOIN job_status       s1 ON s1.job_status_id = j1.job_status_id
  JOIN sub_subactivity  sa ON sa.sub_Code      = j1.job_type_id
  JOIN task             t  ON t.job_id         = j1.job_id
  LEFT JOIN task_assign ta ON ta.task_id       = t.task_id
 WHERE j1.discontinue_date IS NULL
   AND j1.job_submitted = 'Y'
   AND j1.job_status_id <> 7
   AND j1.is_active = 1
   AND ( ( j1.job_type_id IN (8,5,6,9,19,19,7,16,17)
         AND (  FIND_IN_SET(134,p1.sr_manager)
             OR FIND_IN_SET(134,p1.manager)
             OR FIND_IN_SET(134,p1.tl1)
             OR FIND_IN_SET(134,p1.tl2)
             OR FIND_IN_SET(134,p1.tl3)
             OR FIND_IN_SET(134,p1.tl4)
             OR FIND_IN_SET(134,p1.sales)
             )
         )
       OR ta.assignee_id IN (134)
       )
 ORDER BY j1.job_received DESC, j1.job_id DESC
 LIMIT 0,25
选择不同的j1.job\u id
,j1.job_name
,j1.客户机识别码
,j1.job\u status\u id
,j1.int\u作业\u状态\u id
,j1.作业类型\u id
,j1.工作到期日
,j1.job_已收到
,c1.客户名称
,c1.id
,j1.5周期
,j1.5注释
,j1。职员须知
,j1.job_体裁
,j1.job_已提交
,j1.mas_代码
,日期格式(j1.job_completed_DATE,“%d/%m/%Y”)为completedDate
,j1.invoiceno
,j1.0是否处于激活状态
,p1.name
,s1.job_状态
来自作业j1
在c1上加入客户端c1。客户端id=j1。客户端id
在p1.id=c1.id上加入pr_实践p1
在s1上加入作业状态s1。作业状态id=j1。作业状态id
在sa上连接子活动sa。子活动代码=j1。作业类型\U id
在t.job\u id=j1.job\u id上加入任务t
左连接任务\u在ta上分配ta.task\u id=t.task\u id
其中j1.contract_date为空
和j1.job_submitted='Y'
和j1.job_status_id 7
和j1.1是否处于激活状态=1
和((8,5,6,9,19,19,7,16,17)中的作业类型id)
和(在\u集合中查找\u(134,p1.sr\u管理器)
或在_集合中查找_(134,p1.manager)
或在_集合中查找_(134,p1.tl1)
或者在_集合中查找_(134,p1.tl2)
或者在_集合中查找_(134,p1.tl3)
或者在_集合中查找_(134,p1.tl4)
或在_集合中查找_(134,p1.销售)
)
)
或(134)中的ta.U id
)
按j1.job\u接收说明、j1.job\u id说明订购
限值0,25

请注意,
或ta.assignment\u id
谓词忽略j1.job\u type\u id上的谓词,因为AND和OR布尔运算符具有优先级。在重新编写的查询中添加参数将保留此行为。另外,原始查询的
WHERE
子句中的
t.job\u id=j1.job\u id
谓词有效地否定了
左连接任务t
操作的“外部性”,将其等效于
内部联接

使用
解释
找出要使用的索引。或者从查询中一次删除一个表,直到找到慢速联接为止。然后添加适当的索引以加快速度。
FIND_IN_SET(134,p1.sr_manager)
为什么要将旧的前ansi联接与ansi联接相结合?什么只需连接所有表注意:此查询的规范与原始查询略有不同。给定
/
布尔运算符的优先顺序,在原始语句中,
ta.assignment\u id
谓词上有
条件时,
j1.job\u type\u id
上的条件不适用。同样在原文中,
WHERE
子句中的
t.job\u id=j1.job\u id
谓词有效地否定了
左连接任务t
操作的“外部性”。
SELECT DISTINCT j1.job_id
     , j1.job_name
     , j1.client_id
     , j1.job_status_id
     , j1.int_job_status_id
     , j1.job_type_id
     , j1.job_due_date
     , j1.job_received
     , c1.client_name
     , c1.id
     , j1.period
     , j1.notes
     , j1.staff_notes
     , j1.job_genre
     , j1.job_submitted
     , j1.mas_Code
     , DATE_FORMAT(j1.job_completed_date, '%d/%m/%Y') AS completedDate
     , j1.invoiceno
     , j1.is_active
     , p1.name
     , s1.job_status
  FROM job              j1
  JOIN CLIENT           c1 ON c1.client_id     = j1.client_id
  JOIN pr_practice      p1 ON p1.id            = c1.id
  JOIN job_status       s1 ON s1.job_status_id = j1.job_status_id
  JOIN sub_subactivity  sa ON sa.sub_Code      = j1.job_type_id
  JOIN task             t  ON t.job_id         = j1.job_id
  LEFT JOIN task_assign ta ON ta.task_id       = t.task_id
 WHERE j1.discontinue_date IS NULL
   AND j1.job_submitted = 'Y'
   AND j1.job_status_id <> 7
   AND j1.is_active = 1
   AND ( ( j1.job_type_id IN (8,5,6,9,19,19,7,16,17)
         AND (  FIND_IN_SET(134,p1.sr_manager)
             OR FIND_IN_SET(134,p1.manager)
             OR FIND_IN_SET(134,p1.tl1)
             OR FIND_IN_SET(134,p1.tl2)
             OR FIND_IN_SET(134,p1.tl3)
             OR FIND_IN_SET(134,p1.tl4)
             OR FIND_IN_SET(134,p1.sales)
             )
         )
       OR ta.assignee_id IN (134)
       )
 ORDER BY j1.job_received DESC, j1.job_id DESC
 LIMIT 0,25