2012-04-12 12 views
0

Wir große Datenbank haben, haben wir fast zwei See Aufzeichnungen, während wir versuchen, mit folgenden Abfrage suchen zu lange dauert das ErgebnisMysql Abfrageoptimierung für große Datenbank

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

zu bringen

bearbeiten, haben wir Anfragen in der Schleife mehr abgeleitet, so dass ich mehr Optimierung benötigen @DRapp bezüglich

Antwort

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' 
) 

Dank

+0

So gut wie möglich, können Sie beschreiben, was Sie versuchen, zu bekommen, und was ist "fast zwei Lake Records"? – DRapp

Antwort

1

Ich habe Ihre Anfrage neu strukturiert. Einige der where-Klauseln waren redundant (in Bezug auf e.owner_guid = 130), so dass überflüssige Elemente entfernt wurden.

Ich habe die MySQL-Klausel "STRAIGHT_JOIN" hinzugefügt, um der Engine mitzuteilen, dass sie in der von den Tabellen und den jeweiligen Joins bereitgestellten Reihenfolge ausgeführt werden soll. Ich habe mit Ihrem "m1" als FIRST Prequery begonnen, um auch Ihre Kriterien für "name_id" und "String" Qualifier einzubeziehen. Stellen Sie sicher, dass Ihre Tabelle "elgg_metadata" über einen Index für die Spalte "name_id" verfügt. Da Sie nichts mit einer der anderen Spalten aus der Metadaten- oder Metastring-Tabelle tun (außer um sich zu qualifizieren), gebe ich nur die DISTINCT "entity_id" zurück. Dies sollte eine schnelle kleine Teilmenge für Sie zurückgeben.

Von diesem Ergebnis nur Join diejenigen vorqualifiziert für Ihre Entitäten, Benutzer und Beziehungen Tabellen (links Join auf die Beziehungen seit das war eine "ODER" Bedingung später). Wenn die Entitäts-ID nicht gefunden werden kann, gehen Sie nicht weiter.

DANN kann der Rest der OR-Kriterien angewendet werden ... wenn der owner_guid = 130 ODER gefunden in eer (Beziehungen) über Links-Join vs ein IN (subselect) was wäre ein Performance-Killer und Ihr Finale ODER für die Zugriffs-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) 
+0

@selva, huh ???? – DRapp

+0

Können Sie diesen Link überprüfen http://stackoverflow.com/a/10196376/1329306 – selva

+0

Bitte überprüfen Sie meine Abfrage editieren – selva