Mysql查询优化

时间:2011-05-11 21:50:19

标签: mysql optimization indexing

跟随查询:

  SELECT tbl_yaca_sites.`id_site` FROM `tbl_yaca_sites`
   INNER JOIN `tbl_relation` ON tbl_relation.id_website = tbl_yaca_sites.id_site
   INNER JOIN `tbl_yaca_directories` ON tbl_yaca_directories.id_record = tbl_relation.id_category
   INNER JOIN `tbl_applications` ON tbl_applications.id_site = tbl_yaca_sites.id_site
  where
  tbl_applications.id_application IN (41)
  and tbl_yaca_directories.type = 0
  AND tbl_yaca_directories.work = 1
  AND tbl_relation.work = 1  GROUP BY tbl_yaca_sites.`id_site`

有许多索引:

  1. tbl_yaca_sites - 主要id_site和另一个id_site(相同字段,但另一个索引)
  2. tbl_relation - 主要ID和组合索引(id_site,id_category,work)
  3. tbl_yaca_directories - 主要用于id_record和组合索引'type'(类型,工作)
  4. tbl_applications - 没有主要的。有一个索引id_application。
  5. 当我仅设置描述索引时(但没有'group by'),查询效果很好。我测试了很多次。

    因此,如果我在没有组的情况下运行此查询需要一秒钟。足够好的结果,每张表中大约有200 000条记录。添加'分组',总是需要16秒。

    如果我按照操作:

    SELECT id_site FROM (SELECT tbl_yaca_sites.`id_site` FROM `tbl_yaca_sites`
       INNER JOIN `tbl_relation` ON tbl_relation.id_website = tbl_yaca_sites.id_site
       INNER JOIN `tbl_yaca_directories` ON tbl_yaca_directories.id_record = tbl_relation.id_category
       INNER JOIN `tbl_applications` ON tbl_applications.id_site = tbl_yaca_sites.id_site
      where
      tbl_applications.id_application IN (41)
      and tbl_yaca_directories.type = 0
      AND tbl_yaca_directories.work = 1
      AND tbl_relation.work = 1 ) as tbl GROUP BY id_site
    

    需要1,7秒。

    这是解释查询:

    1, 'SIMPLE', 'tbl_yaca_sites', 'index', 'PRIMARY,id_site', 'PRIMARY', '4', '', 102358, 'Using index'
    1, 'SIMPLE', 'tbl_applications', 'ref', 'pair', 'pair', '8', 'webservices.tbl_yaca_sites.id_site,const', 1, 'Using index'
    1, 'SIMPLE', 'tbl_relation', 'ref', 'comb', 'comb', '4', 'webservices.tbl_yaca_sites.id_site', 1, 'Using where; Using index'
    1, 'SIMPLE', 'tbl_yaca_directories', 'eq_ref', 'PRIMARY,type', 'PRIMARY', '4', 'webservices.tbl_relation.id_category', 1, 'Using where'
    

    还尝试添加count(*)| count(id_site)|算(1)。结果一样。

    为什么这么久?有谁能告诉我我错过了什么?

    提前感谢大家!

2 个答案:

答案 0 :(得分:1)

您也可以尝试:

SELECT DISTINCT tbl_yaca_sites.`id_site`
FROM `tbl_yaca_sites`
INNER JOIN `tbl_relation` ON tbl_relation.id_website = tbl_yaca_sites.id_site
INNER JOIN `tbl_yaca_directories` ON tbl_yaca_directories.id_record = tbl_relation.id_category
INNER JOIN `tbl_applications` ON tbl_applications.id_site = tbl_yaca_sites.id_site
WHERE
     tbl_applications.id_application IN (41)
     AND tbl_yaca_directories.type = 0
     AND tbl_yaca_directories.work = 1
     AND tbl_relation.work = 1

答案 1 :(得分:0)

鉴于您只需要唯一的id_site值列表,您可以只使用In子句:

Select id_site
From tbl_yaca_sites 
Where id_site In    (
                    Select id_site
                    From tbl_yaca_sites
                        Join tbl_relation 
                            On tbl_relation.id_website = tbl_yaca_sites.id_site
                        Join tbl_yaca_directories 
                            On tbl_yaca_directories.id_record = tbl_relation.id_category
                        Join tbl_applications 
                            On tbl_applications.id_site = tbl_yaca_sites.id_site
                    Where tbl_applications.id_application In(41)
                        And tbl_yaca_directories.type = 0
                        And tbl_yaca_directories.work = 1
                        And tbl_relation.work = 1
                    )