si想要优化这个需要大量时间执行的查询。
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
客户表
client_id int(11) | id int(11) (practice Id)
练习表
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
请指教!
答案 0 :(得分:0)
试试这个:
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
答案 1 :(得分:0)
问题并不能识别任何表格上的任何索引。
SQL性能的关键是了解优化器可用的操作,以及MySQL如何确定从可用的操作中选择哪些操作。拥有合适的索引可以使MySQL能够利用这些索引来实现更高效的执行计划。
如果没有EXPLAIN
的输出,我们就会猜测执行计划。
我们对性能降低的最初的下意识反应是添加适当的指数。或者第二个想法是,当谓词包含OR
条件时,MySQL并不总能做出最有效的选择。 LIMIT子句最后应用于处理... MySQL将在应用LIMIT之前处理整个结果集上的DISTINCT和ORDER BY操作。并且Using 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
关键字语法,并将连接谓词从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
请注意,由于AND和OR布尔运算符的优先级,OR ta.assignee_id
谓词忽略j1.job_type_id上的谓词。在重写的查询中添加parens会保留此行为。此外,原始查询的t.job_id = j1.job_id
子句中的WHERE
谓词有效地否定了&#34;外部性&#34; LEFT JOIN task t
操作,使其等同于INNER JOIN
。