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
A scanuje je se mi celá tabulka, resp. v explainu je téměř celá tabula, já potřebuji jen posledních 10 IDček podle ORDER klíče.

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 *
Od boku - přesuň id NOT IN (34096) do HAVING a udělej index na (zobrazit, datum_fake, datum_vytvoreni).
Kajman
Profil
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
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 *
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
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
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.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: