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

Jak optimalizovat dotaz, pokud tabulka obsahuje 10 000 položek pomocí MySQL?

Pokusil bych se to ÚPLNĚ zjednodušit tím, že na vaše ostatní tabulky vložím spouštěče a do vaší tabulky User_Fans přidám jen několik sloupců... Jeden pro každý příslušný počet(), který se snažíte získat... z příspěvků, příspěvků, příspěvků, komentářů, Přidat komentář Líbí se mi.

Když je záznam přidán do kterékoli tabulky, stačí aktualizovat tabulku user_fans tak, aby přidala 1 do počtu... bude to prakticky okamžité na základě ID klíče uživatele. Pokud jde o "LIKES"... Podobné, pouze pod podmínkou, že se něco spustí jako "To se mi líbí", přidejte 1.. Pak bude váš dotaz přímou matematikou na jediném záznamu a nebude se spoléhat na ŽÁDNÁ spojení při výpočtu "vážená" celková hodnota. Jak se vaše tabulka bude ještě zvětšovat, budou se také prodlužovat dotazy, protože mají více dat, která je třeba prolít a agregovat. Procházíte KAŽDÝ záznam user_fan, který v podstatě dotazuje každý záznam ze všech ostatních tabulek.

Vše, co bylo řečeno, ponechat tabulky tak, jak je máte, bych restrukturalizoval následovně...

SELECT 
      uf.user_name,
      uf.user_id,
      @pc := coalesce( PostSummary.PostCount, 000000 ) as PostCount,
      @pl := coalesce( PostLikes.LikesCount, 000000 ) as PostLikes,
      @cc := coalesce( CommentSummary.CommentsCount, 000000 ) as PostComments,
      @cl := coalesce( CommentLikes.LikesCount, 000000 ) as CommentLikes,
      @pc + @cc AS sum_post,
      @pl + @cl AS sum_like, 
      @pCalc := (@pc + @cc) * 10 AS post_cal,
      @lCalc := (@pl + @cl) * 5 AS like_cal,
      @pCalc + @lCalc AS `total`
   FROM
      ( select @pc := 0,
               @pl := 0,
               @cc := 0,
               @cl := 0,
               @pCalc := 0
               @lCalc := 0 ) sqlvars,
      user_fans uf
        LEFT JOIN ( select user_id, COUNT(*) as PostCount
                       from post
                       group by user_id ) as PostSummary
           ON uf.user_id = PostSummary.User_ID

        LEFT JOIN ( select user_id, COUNT(*) as LikesCount
                       from post_likes
                       group by user_id ) as PostLikes
           ON uf.user_id = PostLikes.User_ID

        LEFT JOIN ( select user_id, COUNT(*) as CommentsCount
                       from post_comment
                       group by user_id ) as CommentSummary
           ON uf.user_id = CommentSummary.User_ID

        LEFT JOIN ( select user_id, COUNT(*) as LikesCount
                       from post_comment_likes
                       group by user_id ) as CommentLikes
           ON uf.user_id = CommentLikes.User_ID

   ORDER BY 
      `total` DESC 
   LIMIT 20

My variables are abbreviated as 
"@pc" = PostCount
"@pl" = PostLikes
"@cc" = CommentCount
"@cl" = CommentLike
"@pCalc" = weighted calc of post and comment count * 10 weighted value
"@lCalc" = weighted calc of post and comment likes * 5 weighted value

LEVÉ PŘIPOJENÍ k předdotazům provede tyto dotazy JEDNOU, pak se celá věc spojí, místo aby byla zasažena jako dílčí dotaz pro každý záznam. Při použití COALESCE(), pokud ve výsledcích tabulky LEFT JOINed žádné takové položky nejsou, nezasáhnete hodnoty NULL, které zkazí výpočty, takže jsem je nastavil na 000000.

OBjasnění VAŠICH OTÁZEK

Jako "AS AliasResult" můžete mít jakýkoli DOTAZ. "As" lze také použít ke zjednodušení dlouhých názvů tabulek pro snazší čitelnost. Aliasy mohou také používat stejnou tabulku, ale jako jiný alias k získání podobného obsahu, ale pro jiný účel.

select
      MyAlias.SomeField
   from
      MySuperLongTableNameInDatabase MyAlias ...

select
      c.LastName,
      o.OrderAmount
   from
      customers c
         join orders o
            on c.customerID = o.customerID  ...

select
      PQ.SomeKey
   from
      ( select ST.SomeKey
           from SomeTable ST
           where ST.SomeDate between X and Y ) as PQ
         JOIN SomeOtherTable SOT
            on PQ.SomeKey = SOT.SomeKey ...

Nyní třetí dotaz výše není praktický a vyžaduje ( úplný dotaz, jehož výsledkem je alias "PQ" představující "PreQuery"). To lze provést, pokud jste chtěli předem omezit určitou sadu dalších komplexních podmínek a chtěli byste menší sadu PŘED provedením dalších spojení k mnoha dalším tabulkám pro všechny konečné výsledky.

Protože „FROM“ NEMUSÍ být skutečnou tabulkou, ale může to být dotaz sám o sobě, na jakémkoli jiném místě použitém v dotazu, musí vědět, jak na tuto sadu výsledků předběžného dotazu odkazovat.

Také při dotazování na pole mohou být také „Jako FinalColumnName“, aby se výsledky zjednodušily tam, kde budou také použity.

selectCONCAT( User.Salutation, User.LastName ) as CourtesyNamefrom ...

selectOrder.NonTaxable+ Order.Taxable+ ( Order.Taxable * Order.SalesTaxRate ) jako OrderTotalWithTaxfrom ...

Název sloupce „Jak“ NENÍ povinný být souhrnem, ale nejčastěji se tak zobrazuje.

Nyní, s ohledem na proměnné MySQL... Pokud jste prováděli uloženou proceduru, mnoho lidí jim předem deklaruje nastavení výchozích hodnot před zbytkem procedury. Můžete je provést in-line v dotazu pouhým nastavením a uvedením výsledku odkazu "Alias". Při provádění těchto proměnných bude select simulovat vždy vracení JEDNOHO ZÁZNAMU hodnot. Je to skoro jako jeden záznam s možností aktualizace použitý v dotazu. Nemusíte aplikovat žádné specifické podmínky "Připojit", protože to nemusí mít žádný vliv na zbytek tabulek v dotazu... V podstatě vytvoří kartézský výsledek, ale jeden záznam proti jakékoli jiné tabulce nikdy nevytvoří stejně duplikuje, takže žádné poškození po proudu.

select 
       ...
   from 
      ( select @SomeVar := 0,
               @SomeDate := curdate(),
               @SomeString := "hello" ) as SQLVars

Nyní, jak fungují sqlvars. Představte si lineární program... Jeden příkaz se provede v přesném pořadí, jak běží dotaz. Tato hodnota je poté znovu uložena zpět do záznamu "SQLVars" připraveného pro další použití. Neodkazujete však na něj jako na SQLVars.SomeVar nebo SQLVars.SomeDate... pouze na @SomeVar :=someNewValue. Nyní, když je @var použit v dotazu, je také uložen jako "Jako název_sloupce" v sadě výsledků. Někdy to může být jen zástupná vypočítaná hodnota při přípravě dalšího záznamu. Každá hodnota je pak přímo dostupná pro další řádek. Takže s ohledem na následující příklad...

select
      @SomeVar := SomeVar * 2 as FirstVal,
      @SomeVar := SomeVar * 2 as SecondVal,
      @SomeVar := SomeVar * 2 as ThirdVal
   from
      ( select @SomeVar := 1 ) sqlvars,
      AnotherTable
   limit 3

Will result in 3 records with the values of 

FirstVal    SecondVal   ThirdVal
2           4           8
16          32          64
128         256         512

Všimněte si, jak se používá hodnota @SomeVar, když ji používá každý sloupec... Takže i na stejném záznamu je aktualizovaná hodnota okamžitě k dispozici pro další sloupec... To znamená, nyní se podívejte na pokus o vytvoření simulovaného počtu záznamů / pořadí na každého zákazníka...

select
      o.CustomerID,
      o.OrderID
      @SeqNo := if( @LastID = o.CustomerID, @SeqNo +1, 1 ) as CustomerSequence,
      @LastID := o.CustomerID as PlaceHolderToSaveForNextRecordCompare
   from
      orders o,
      ( select @SeqNo := 0, @LastID := 0 ) sqlvars
   order by
      o.CustomerID

Klauzule "Objednat podle" vynutí, aby byly výsledky vráceny v pořadí jako první. Zde jsou tedy vráceny záznamy na zákazníka. Poprvé je LastID 0 a ID zákazníka je řekněme...5. Protože se liší, vrátí 1 jako @SeqNo, POTOM zachová toto ID zákazníka do pole @LastID pro další záznam. Nyní další záznam pro zákazníka... Poslední ID je stejné, takže vezme @SeqNo (nyní =1) a přidá 1 k 1 a stane se #2 pro stejného zákazníka... Pokračujte v cestě.. .

Pokud jde o zlepšení v psaní dotazů, podívejte se na značku MySQL a podívejte se na některé z velkých přispěvatelů. Podívejte se na otázky a některé složité odpovědi a na to, jak funguje řešení problémů. Neříkám, že tu nejsou jiní s nižším skóre reputace, kteří teprve začínají a jsou zcela kompetentní, ale zjistíte, kdo dává dobré odpovědi a proč. Podívejte se také na jejich historii zveřejněných odpovědí. Čím více budete číst a sledovat, tím lépe zvládnete psaní složitějších dotazů.



  1. Seskupené souhrnné Pushdown

  2. Oznámení o změně s SQL Server 2008

  3. Vysvětlení SQL Server Příkaz ALTER TABLE ADD COLUMN

  4. Jak smazat data z Elastisearch