Autor | Zpráva | ||
---|---|---|---|
Kcko Profil |
Tabulka cca několik desítek tisíc řádku, dotaz
SELECT SQL_CALC_FOUND_ROWS id FROM clanky WHERE zobrazit = 1 AND id NOT IN (34096) ORDER BY datum_fake DESC, datum_vytvoreni DESC LIMIT 10 Zkoušel jsem indexy samostatně i složeně a nic moc to nedělá. Mysql verze 5.5+ Dá se to nějak zoptimalizovat? |
||
TomášK. Profil * |
#2 · Zasláno: 5. 2. 2018, 13:00:21
Od boku - přesuň
id NOT IN (34096) do HAVING a udělej index na (zobrazit, datum_fake, datum_vytvoreni) .
|
||
Kajman Profil |
#3 · Zasláno: 5. 2. 2018, 13:03:39
Souhlasím s TomášemK.
Zkus dát tu podmínku, co skoro vždy vyhoví, do having části (sloupec musí být uveden v select části). Tedy při dvousloupcovém indexu (zobrazit, datum_fake) by mělo být rychlé. SELECT id FROM clanky WHERE zobrazit = 1 HAVING id NOT IN (34096) ORDER BY datum_fake DESC, datum_vytvoreni DESC LIMIT 10 Problém je to SQL_CALC_FOUND_ROWS. S tím to asi rychlé nebude a počet řádků ale bude potřeba asi vypočítat dotazem navíc select (select count(*) from clanky where zobrazit=1) - (select count(*) from clanky where zobrazit=1 and id in (34096)) pocet Nebo tam tu podmínku nedávat, udělat limit 11 a řádek navíc nebo ten se špatným id vyfiltrovat v aplikaci. |
||
Kcko Profil |
#4 · Zasláno: 5. 2. 2018, 13:25:26
TomášK., Kajman:
Dělá to SQL_CALC_FOUND_ROWS Resp. takto, nekoukal jsem předtím na execution time, spíše na počet řádků a ladil jsem nesmysl. Vždy to musí vybrat v podstatě celou tabulku, protože vypnutých článků je tam minimum. Můj prvotní dotaz se SCFR je cca 0,08, bez 0,05, vámi navržená optimalizace je 0,04/0,05 Nicméně je pro mě novinka, presunout do HAVING, X let žiji v domnění že HAVING slouží k omezení zgrupnutých řádků. SCFR používám po celém webu, takže udělám spíš nějaké aplikační kešování (Ono jak jsem psal, pomalé to není, spíše mě vždy vyděsil ten počet řádků, ale to je IMHO v pořádku). |
||
TomášK. Profil * |
#5 · Zasláno: 5. 2. 2018, 14:23:47
Kcko:
„Nicméně je pro mě novinka, presunout do HAVING, X let žiji v domnění že HAVING slouží k omezení zgrupnutých řádků.“ A nejspíš máš pravdu a v omylu žiju já a ještě ho šířím. HAVING se vyhodnocuje před ORDER BY , tedy by to nejspíš nepomohlo. Pro filtrování až nakonec by bylo potřeba to obalit naddotazem (je to vůbec slovo?).
|
||
Kajman Profil |
#6 · Zasláno: 5. 2. 2018, 14:45:35
Pokud to bez SCFR nejde, tak bych having nepoužíval.
Ta finta s having jde v mysql (vím, že nějaké jiné databáze vyžadují i group by klauzuli). Jde o to, že když je podmínka, co vyhoví téměř vždy, tak může být rychlejší ji kontrolovat až postupně pro seřazené záznamy. (A když to plánovač databáze sám neumí, dalo se mu takto pomoci, možná už by to bylo v mariadb svižnější.) Tedy pokud bude index nad sloupcem datum_fake a dám SELECT id FROM clanky ORDER BY datum_fake DESC LIMIT 10 Bude to rychlé a když přidám do select části zobrazit a přidám HAVING zobrazit = 1 AND id NOT IN (34096) tak se postupně ty články kontrolují až po seřazení a skončí se, až se limit naplní. Pokud ta podmínka platí skoro vždy a limit není velký, tak to bývá skoro stejně rychlé, jak ten původní dotaz. Používal jsem to kdysi tady k ofiltrování "U ledu" z výpisů. U některých sestav to byl výrazný rozdíl, někde minimální. |
||
Kcko Profil |
#7 · Zasláno: 5. 2. 2018, 15:24:06
TomášK.:
No pamatuji si to snad od doby, kdy jsem se začínal učit SQL SELECT FROM WHERE GROUP HAVING ORDER LIMIT. Je možné, to co píše Kajman, ale je to přinejmenším divné. Díky oboum. |
||
Časová prodleva: 6 let
|
0