2015-06-25 129 views
1

我们有一个本土文件管理系统,我们的系统运行速度很慢,特别是在搜索时。它起初运行良好,但随着时间的推移,它逐渐变慢。它现在需要30到150秒的时间来根据标准返回结果。这是我们的搜索查询。我们一直在左右盯着这个东西,看不到任何地方调整这个更多。所有连接的字段都在其各自的表上建立索引。MySQL查询性能限制?

SELECT DISTINCT f.*, ts.*, fo.*, ft.*, p.*, u.*, c.*, co.*, ct.*, fs.*, fd.*, r.*, rt.*, si.*, s.* FROM (
SELECT DISTINCT f.* FROM files f 
JOIN folders fo ON(fo.id = f.belongs_to_folder_id) 
JOIN projects p ON(p.id = f.belongs_to_project_id) 
LEFT OUTER JOIN file_statuses fs ON(fs.id = f.file_status_id) 
LEFT OUTER JOIN submittal_items_files sif ON(sif.file_id = f.id) 
LEFT OUTER JOIN submittal_items si ON(si.id = sif.submittal_item_id) 
LEFT OUTER JOIN submittals s ON(s.id = si.belongs_to_submittal_id) 
LEFT OUTER JOIN record_types rt ON(rt.id = f.record_type_id) 
LEFT OUTER JOIN companies co ON(co.id = f.company_id) 
LEFT JOIN folders_actions_groups ag ON (
    f.belongs_to_folder_id = ag.folder_id AND 
    ag.action_id = 10010 
) 
LEFT JOIN files_actions_groups fg ON (fg.file_id = f.id) 
JOIN users_groups ug ON ((ug.group_id = ag.group_id OR ug.group_id = fg.group_id) AND ug.user_id = 411) 
WHERE (
    (f.file_generated_name LIKE CONCAT('%', 'the', '%')) OR 
    (f.record_id LIKE CONCAT('%', 'the', '%')) OR 
    (f.record_title LIKE CONCAT('%', 'the', '%')) OR 
    (f.additional_info LIKE CONCAT('%', 'the', '%')) OR 
    (si.item_number LIKE CONCAT('%', 'the', '%')) OR 
    (s.element_number LIKE CONCAT('%', 'the', '%')) 
) AND f.path LIKE CONCAT('Some Text', '%') AND 
f.file_status_id = 3 AND 
f.file_revision = 1 AND 
f.discipline_id = 1 AND 
f.record_type_id = 2 AND 
f.triage_status_id = 2 AND 
f.deleted = 0 
ORDER BY f.created DESC, f.id DESC 
LIMIT 100 
) AS f 
LEFT OUTER JOIN users u ON(f.created_by_user_id = u.id) 
LEFT OUTER JOIN contacts c ON(c.user_id = u.id) 
LEFT OUTER JOIN companies co ON(co.id = f.company_id) 
LEFT OUTER JOIN company_types ct ON(ct.id = co.company_type_id) 
JOIN triage_statuses ts ON(f.triage_status_id = ts.id) 
JOIN folders fo ON(fo.id = f.belongs_to_folder_id) 
JOIN folder_types ft ON(ft.id = fo.folder_type_id) 
JOIN projects p ON(p.id = f.belongs_to_project_id) 
LEFT OUTER JOIN file_statuses fs ON(fs.id = f.file_status_id) 
LEFT OUTER JOIN file_disciplines fd ON(fd.id = f.discipline_id) 
LEFT OUTER JOIN revisions r ON(r.id = f.file_revision) 
LEFT OUTER JOIN record_types rt ON(rt.id = f.record_type_id) 
LEFT OUTER JOIN submittal_items_files sif ON(sif.file_id = f.id) 
LEFT OUTER JOIN submittal_items si ON(si.id = sif.submittal_item_id) 
LEFT OUTER JOIN submittals s ON(s.id = si.belongs_to_submittal_id) 
LEFT OUTER JOIN files_actions_groups ffg ON(ffg.file_id = f.id) 
LEFT OUTER JOIN groups g ON(g.id = ffg.group_id) 
ORDER BY f.created DESC, f.id DESC 
+0

您是否需要*返回所有数据?来自每个单一连接表的每一列?我还建议找出一种方法来分解重复的LIKE CONCAT('%','''''''')子句。 –

+0

使用'EXPLAIN'和'EXPLAIN EXTENDED'来查看成本是多少? –

+0

查看全文搜索或使用sphinx这样的强大的文本搜索mysql – Mihai

回答

0

这可能是一个明显的答案,但你有没有索引的数据库?如果您不熟悉索引,那么这里有一个非常好的规则:只需在名为“id”的所有列上放置一个唯一索引,例如folders.id或projects.id,然后将标准索引放在所有引用国外的ID,如folder.belongs_to_folder_id或folder.record_type_id

我会改变的另一件事是,试图只选择将实际使用,而不是你的巨大的f.*, ts.*, fo.*, ft.*, p.*, u.*, c.*, co.*, ct.*, fs.*, etc...

列表中的列也有加入的吨,这在处理时间方面非常昂贵。你真的需要所有的表格吗?

+0

所有涉及连接的字段都被编入索引。我想我可以在一定程度上限制这些领域。 '。*'维护费用低,是否有大量的性能问题?这些表格都有我们必须在搜索结果中显示的值,所以我们确实需要连接。有没有更高效的方法? –