Mysql查询优化大型数据库

时间:2012-04-12 14:19:03

标签: mysql query-optimization

我们有大型数据库,我们有近两个湖泊记录,而我们尝试使用下面的查询搜索花费太长时间才能得出结果

myquery

SELECT 
      count( DISTINCT e.guid ) AS total
   FROM 
      elgg_entities e
         JOIN elgg_users_entity u 
            ON e.guid = u.guid
         JOIN ( SELECT 
                      subm1.*, 
                      s1.string
                   FROM 
                      elgg_metadata subm1
                         JOIN elgg_metastrings s1 
                            ON subm1.value_id = s1.id ) AS m1 
            ON e.guid = m1.entity_guid
   WHERE 
          m1.name_id = '332'
      AND m1.string LIKE '%96059%'
      AND ( (     e.access_id = -2
              AND e.owner_guid IN ( SELECT guid_one
                                        FROM elgg_entity_relationships
                                        WHERE relationship = 'friend'
                                           AND guid_two =130 )
            )
            OR 
            (     e.access_id IN ( 2, 1, 3, 4, 6, 7 )
              OR ( e.owner_guid = 130 )
              OR (     e.access_id = 0
                   AND e.owner_guid = 130 )
            )
            AND e.enabled = 'yes'
          )

my query explain

编辑,我们在循环中有更多的派生查询,所以我需要更多关于@DRapp

的优化

答案

SELECT count( DISTINCT e.guid ) AS total
FROM elgg_entities e
JOIN elgg_users_entity u ON e.guid = u.guid
JOIN (

SELECT subm1 . * , s1.string
FROM elgg_metadata subm1
JOIN elgg_metastrings s1 ON subm1.value_id = s1.id
) AS m1 ON e.guid = m1.entity_guid
JOIN (

SELECT subm2 . * , s2.string
FROM elgg_metadata subm2
JOIN elgg_metastrings s2 ON subm2.value_id = s2.id
) AS m2 ON e.guid = m2.entity_guid
WHERE (
(
subm1.name_id = '332'
AND s1.string LIKE '%10001%'
)
AND (
subm2.name_id = '328'
AND s2.string LIKE '%New York%'
)
)
AND (
(
e.access_id = -2
AND e.owner_guid
IN (

SELECT guid_one
FROM elgg_entity_relationships
WHERE relationship = 'friend'
AND guid_two =2336
)
)
OR (
e.access_id
IN ( 2, 1 )
OR (
e.owner_guid =2336
)
OR (
e.access_id =0
AND e.owner_guid =2336
)
)
AND e.enabled = 'yes'
)
AND (
(
subm1.access_id = -2
AND subm1.owner_guid
IN (

SELECT guid_one
FROM elgg_entity_relationships
WHERE relationship = 'friend'
AND guid_two =2336
)
)
OR (
subm1.access_id
IN ( 2, 1 )
OR (
subm1.owner_guid =2336
)
OR (
subm1.access_id =0
AND subm1.owner_guid =2336
)
)
AND subm1.enabled = 'yes'
)
AND (
(
subm2.access_id = -2
AND subm2.owner_guid
IN (

SELECT guid_one
FROM elgg_entity_relationships
WHERE relationship = 'friend'
AND guid_two =2336
)
)
OR (
subm2.access_id
IN ( 2, 1 )
OR (
subm2.owner_guid =2336
)
OR (
subm2.access_id =0
AND subm2.owner_guid =2336
)
)
AND subm2.enabled = 'yes'
)

由于

1 个答案:

答案 0 :(得分:1)

我重新构建了您的查询。其中一些where子句是多余的(相对于e.owner_guid = 130),所以删除了多余的元素。

我添加了MySQL子句“STRAIGHT_JOIN”,告诉引擎按表和各个连接提供的顺序执行。我从你的“m1”作为FIRST预查询开始,还包括你的“name_id”和“String”限定符的标准。确保您的elgg_metadata表在name_id列上有索引。此外,由于您没有对元数据或元字符串表中的任何其他列执行任何操作(限定除外),因此我只返回DISTINCT“entity_id”。这应该为您返回一个快速的小子集。

从该结果中,只将那些预先限定的内容加入到您的实体,用户和关系表中(左键加入关系,因为之后是“OR”条件)。如果找不到实体ID的匹配项,请不要再费力了。

那么,OR标准的其余部分可以应用...如果owner_guid = 130或者在eer(关系)中通过左连接和IN(subselect)找到这将是性能杀手,并且你的最终OR对于Access_ID。

SELECT STRAIGHT_JOIN
      count( DISTINCT e.guid ) AS total
   FROM
      ( SELECT DISTINCT
              subm1.entity_id
           FROM 
              elgg_metadata subm1
                 JOIN elgg_metastrings s1 
                    ON subm1.value_id = s1.id 
           WHERE
                  subm1.name_id = '332'
              AND s1.string LIKE '%96059%' ) AS m1 

         JOIN elgg_entities e
            ON m1.entity_id = e.guid
            AND e.enabled = 'yes'

            JOIN elgg_users_entity u 
               ON e.guid = u.guid

            LEFT JOIN elgg_entity_relationships eer
               ON e.owner_guid = eer.guid_one
               AND eer.relationship = 'friend'
               AND eer.guid_two = 130
               AND e.access_id = -2
   WHERE
         e.owner_guid = 130
      OR eer.guid_one = e.owner_guid
      OR e.access_id IN ( 2, 1, 3, 4, 6, 7 )