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