sql >> Databáze >  >> RDS >> Mysql

lze to provést rychleji s velkým množstvím dat [MySQL]

Podívejte se na svůj EXPLAIN výstup, měl jsem obavy, že vaše použití poddotazů vedlo k neoptimálnímu použití indexů. cítil jsem (bez jakéhokoli odůvodnění - a v tomto se mohu velmi dobře mýlit), že přepisování pomocí JOIN může vést k optimalizaci dotazu.

Abychom to mohli udělat, musíme pochopit, k čemu je váš dotaz určen. Pomohlo by, kdyby to vaše otázka formulovala, ale po malém přemýšlení jsem usoudil, že se váš dotaz pokouší načíst seznam všech ostatních klíčových slov, která se vyskytují v jakémkoli článku, který obsahuje nějaké dané klíčové slovo, spolu s počtem všech článků, ve kterých se tato klíčová slova vyskytují .

Nyní znovu sestavíme dotaz ve fázích:

  1. Načtěte „jakýkoli článek, který obsahuje určité klíčové slovo " (nestarejte se o duplikáty):

    SELECT ca2.article_id
    FROM
           career_article_keyword AS ca2
    WHERE
          ca2.keyword_id = 9;
    
  2. Načtěte „všechna ostatní klíčová slova, která se vyskytují v [výše] "

    ."
    SELECT ca1.keyword_id
    FROM
           career_article_keyword AS ca1
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ca1.keyword_id;
    
  3. Načíst [výše uvedené] spolu s počtem všech článků, ve kterých se tato klíčová slova vyskytují "

    ."
    SELECT ca1.keyword_id, COUNT(DISTINCT ca0.article_id) AS cnt
    FROM
           career_article_keyword AS ca0
      JOIN career_article_keyword AS ca1 USING (keyword_id)
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ca1.keyword_id
    ORDER BY cnt DESC;
    
  4. Nakonec chceme do výstupu přidat samotné odpovídající klíčové slovo z career_keyword tabulka:

    SELECT ck.keyword_id, ck.keyword, COUNT(DISTINCT ca0.article_id) AS cnt
    FROM
           career_keywords        AS ck 
      JOIN career_article_keyword AS ca0 USING (keyword_id)
      JOIN career_article_keyword AS ca1 USING (keyword_id)
      JOIN career_article_keyword AS ca2 ON (ca2.article_id = ca1.article_id)
    WHERE
          ca1.keyword_id <> 9
      AND ca2.keyword_id =  9
    GROUP BY ck.keyword_id -- equal to ca1.keyword_id due to join conditions
    ORDER BY cnt DESC;
    

Jedna věc, která je hned jasná, je, že váš původní dotaz odkazoval na career_keywords dvakrát, zatímco tento přepsaný dotaz odkazuje na tuto tabulku pouze jednou; to samo o sobě může vysvětlit rozdíl ve výkonu – zkuste odstranit druhý odkaz na něj (tj. tam, kde se vyskytuje ve vašem prvním dílčím dotazu), protože je tam zcela nadbytečný.

Při pohledu zpět na tento dotaz můžeme vidět, že spojení se provádějí v následujících sloupcích:

  • career_keywords.keyword_id v ck JOIN ca0

    Tato tabulka definuje PRIMARY KEY (`keyword_id`) , takže existuje dobrý index, který lze pro toto spojení použít.

  • career_article_keyword.article_id v ca1 JOIN ca2

    Tato tabulka definuje UNIQUE KEY `article_id` (`article_id`,`keyword_id`) a od article_id je sloupec zcela vlevo v tomto indexu, existuje dobrý index, který lze pro toto spojení použít.

  • career_article_keyword.keyword_id v ck JOIN ca0 a ca0 JOIN ca1

    Neexistuje žádný index, který lze pro toto spojení použít:jediný index definovaný v této tabulce má další sloupec, article_id nalevo od keyword_id - takže MySQL nemůže najít keyword_id položky v indexu, aniž byste nejprve znali article_id . Navrhuji, abyste vytvořili nový index, který má keyword_id jako jeho sloupec zcela vlevo.

    (Potřeba tohoto indexu mohla být rovněž zjištěna přímo z vašeho původního dotazu, kde vaše dva nejvzdálenější dotazy provádějí spojení v tomto sloupci.)




  1. Jak opravit chybu Microsoft SQL Server 926?- Vyřešeno

  2. Mysql 'VALUES function' je zastaralá

  3. Nastavte hodnotu AUTO_INCREMENT pomocí proměnné v MySql

  4. DECIMÁLNÍ mysql a úložný prostor?