Diskuze: MariaDB explain select type ALL
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.

Člen

Zobrazeno 7 zpráv z 7.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Online test znalostí SQL a databází, jsme si ověřili nabyté zkušenosti z kurzu.
1. Prosim te, jednoradkovymi dotazy se tu nikdo nebude zabyvat. Hezky to zformatuj, aby to bylo prehledne. Aspon pomoci https://www.dpriver.com/…qlformat.htm
SELECT *
FROM `tag_category`
INNER JOIN (SELECT `permission_memory`.`ref_id`
FROM `permission_memory`
WHERE
(
`permission_memory`.`ref_model` = 'app\\modules\\tag\\models\\TagCategory' )
AND ( ( ( `permission_memory`.`entity` IN ( 'owner', 'user' ) )
AND ( `permission_memory`.`entity_id` = 72 ) )
OR ( ( `permission_memory`.`entity` IN
( 'account', 'specialist' ) )
AND ( `permission_memory`.`entity_id` IN (
-1, 33, 3, 752,
-1, 33 ) ) ) ))
AS pm
ON `tag_category`.`id` = pm.ref_id
2. Dalsi vec, co si na tom vsimnes, proc tam davas INNER JOIN? Ten propoji vsechno se vsim. Pokud to nepotrebujes, tak se pouziva LEFT JOIN nebo RIGHT JOIN.
3. Proc to JOINujes tabulku pres SELECT? Je to nutne? Proc nepripojis tu tabulku primo?
LEFT JOIN `permission_memory` ON podminky
4. Proc tam mas tolik zavorek?
5. U podminek je mozna dobre to seradit tak, aby ty, ktere maji indexy a maji malou hodnotu (boolean, integer) byli pred temi, ktere resi stringy. Mysleno tak, ze, pokud je entity_id integer a entity je string, tak prvni bys mel kontrolovat asi integer a pak az string. Sporne je to, kdyz tam mas vycet pres IN. Tam zas asi bude rychlejsi porovnat nejdriv ty stringy. Ale, mozna to mas jako binarni typ. A jako, dlouhy string, ref model by mel byt asi na konci, ne? To by chtelo samozrejme zkusit, kolik to sezere casu.
FROM `tag_category` 't'
LEFT JOIN `permission_memory` `p` ON
p.`ref_id` = `t`.`id`
AND (
`p`.`entity` IN ( 'owner', 'user' ) -- tohle je binarni typ? pokud ne, na konec s nim
AND `p`.`entity_id` = 72
OR
`p`.`entity` IN ( 'account', 'specialist' ) -- tohle je binarni typ? pokud ne, na konec s nim
AND `p`.`entity_id` IN (-1, 33, 3, 752,-1, 33)
)
AND `p`.`ref_model` = 'app\\modules\\tag\\models\\TagCategory' --- tohle nevim, co je, ale stringy na konec
6. Nenapsal jsi zadnou cenu. Proc resit tve problemy, studovat tematiku, kdyz pak neuzivis s tim rodinu?
"Potřebuji vrátit hodnoty z tabulky tag_category podle oprávnění v
permission_memory"
Jeste mne napada, A potrebujes, aby na vystupu byl seznam vsech tag_category?
Pokud ne, mozna by slo skladat dotaz opacne. Primarni mit tabulku
permission_memory a na ni left-joinovat. Opet, teoreticky by to melo byt
rychlejsi a vrati to jen seznam, kam ma pristup
Ad 1 - děkuji, zkusím
Ad 2 - inner join proto, protože potřebuji odpovídající záznamy z obou; pokud použiju left/right, mám podle pořadí tabulek buď všechny z tag_category (nechci, neodpovídá permission) nebo permission_memory (nechci, jsou tam i permission k ostatním číselníkům)
Ad 3 - to jsem upravil, děkuji, aktuálně výsledný dotaz je:
SELECT tg.*
FROM tag_category AS tg
INNER JOIN permission_memory AS pm USE INDEX (idx_ref_id_ref_model)
ON tg.id = pm.ref_id
AND pm.ref_model = 'app\\modules\\tag\\models\\TagCategory'
AND ( ( pm.entity IN ( 'owner', 'user' )
AND pm.entity_id = 72 )
OR ( pm.entity IN ( 'account', 'specialist' )
AND pm.entity_id IN ( -1, 33, 3, 752 ) ) )
ORDER BY tg.name
S touto podobou se dostanu ale stále k ALL a filesort, nevím, jestli jsem vzhledem k tomu, že se z tbl_category vrací téměř celý obsah, dopracovat k něčemu lepšímu; pokud obrátím pořadí, mám i temporary, takže tento výsledek je pořád lepší
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE tg ALL PRIMARY NULL NULL NULL 5 Using filesort
1 SIMPLE pm ref idx_ref_id_ref_model idx_ref_id_ref_model 198 okis_test.tg.id,const 1 Using index condition; Using where
Ad 4 - je to převzaté ze slow_logu a takto to do DB pošle framework
Ad 5 - problém je, že všechno jsou stringy - entity, ref_model
Ad 6 - nebyl na to textbox a u posledních dotazů ve fóru jsem nic podobného nenašel - pokud je potřeba, můžeme se domlouvat, nemám nic proti.
Viz předchozí Ad 2 - pokud použiji libovolnou podobu vnějšího joinu, vrátí mi to celou jednu nebo druhou tabulku.
Otázka pak je, jestli jít po tom, že type je ALL na tabulkách o maximálně 2-3 desítkách záznamů, nebo spíš omezit výskyt filesort, temptable, filetable.
Jak jsem psal. Jestli ti staci zjistit vsechny permition, tak bych si vytahl tabulku "permission_memory", na ni left-joinul tu druhou a pak to cele zgrupoval podle id (pokud tech permition je pro kategorii vice) a v select casti pouzil nejake group_concat, concat nebo tak neco.
Ale, jako, v zasade to nemas asi spatne. Jen bych prehazel poradi sloupcu pro WHERE, aby ty, co porovnavaji integer a sundaji nejvic radku se provedli jako prvni. Coz zase muze byt mozna i filtrovani podle slova do 6 znaku rychlejsi.
Hloupe je, ze tohle tam strkas jako string a neudelal sis k tomu tabulku
pomocnou tabulku s id.
A totez entita, klidne mohla mit tabulku s id. Ona tam evidentne id ma, ale v
tom dotazu ho nepouzijes
pm.entity_id. Totiz, to by nevadilo, ale ty ten druhy select opakujes pro kazdy
radek. Takze, on pokazde znovu a znovu zjistuje podle stringu radek s entitou
AND pm.ref_model = 'app\\modules\\tag\\models\\TagCategory'
pm.entity IN ( 'account', 'specialist' )
Zobrazeno 7 zpráv z 7.