Autor Zpráva
frgg
Profil *
Ahoj mám tabulku pro razení rubrik kde mám
ID_rubrika 
ID_clanek
Na obou dvouch vytvářím klíče, a když chci vytvořit i na druhém tak mi to nabídne
1) vytvořit klíč na jednom sloupci
2) vytvořit složený klíč

co má být ten složený klíč? je tam výhoda?

A měl bych tam dát i primární klíč auto-increment nebo nemusím? wordpress to taky nemá :-), ale četl jsem že innodb si i tak vytváří svůj skrytý klíč.
frgg
Profil *
Když u to seřazuji ORDER BY ID_clanek DESC bude rychlejší když bych řadil podle ID (hlavního klíče, nastavený na autoincrement)?
Keeehi
Profil
frgg:
Tak předně, ono to bude rychlé ať to uděláš správně nebo me, jelikož reálně ten tvůj web bude mít těch článků a kategorií pár*.
Jinak se vyjadřuješ velmi zmateně, takže je těžké pochopit, co chceš vlastně vědět.

Obecně, vazební tabulka pro reprezentaci vztahu M:N může mít klidně jen ty dva sloupce. V databázovém návrhu podle normálních forem by klíčem byl celý záznam, tedy oba sloupce. Při převodu návrhu do reálné databáze to tak může zůstat. Primárním klíčem můžou být oba sloupce dohromady - tedy složený klíč. Můžeš ovšem z technických důvodů se rozhodnout, že nechceš používat tento přirozený klíč ale chceš tam přidat umělý klíč. Což pak bude klasický ID sloupec s autoincrementem. Což se může hodit pokud relace má i další atributy, jako třeba čas vytvoření a autora té vyzby a ty bys měl možnost je v administraci editovat. V takovém případě je jednodušší mít tam ten umělý klíč, protože pro identifikaci záznamu ti stačí jedna hodnota. Kdyby jsi používal složený klíč, musel bys v administraci mezi požadavky přenášet hodnoty všech sloupců z toho složeného klíče pro jedinečnou identifikaci.

Co se řazení týče, tak jsem ještě nikdy neviděl, že by se řadilo podle jednoduché vazební tabulky. Stejná data (IDčka) máš v těch tabulkách co je spojuje a tam mají určitě indexy, jelikož to jsou klíče. Jak funguje interně index přes více sloupců nevím a tedy ani, zda se dá použít jen pro jejich podmnožinu. Myslím že to nejde. Můžeš mít ale v tabulce více indexů. Klidně jeden pro první sloupec, druhý pro druhý sloupec a třetí pro jejich kombinaci. Nicméně indexy se úplně asi zabývat nemusíš, dají se přidat když to bude až potřeba.

* Pár v tomto případě znamená třeba do tisíce.
frgg
Profil *
Keeehi:
Co se řazení týče, tak jsem ještě nikdy neviděl, že by se řadilo podle jednoduché vazební tabulky.
SELECT c.*, r.nazev
FROM razeni_rubrik AS rr
JOIN clanek AS c ON tr.ID_clanek = c.ID
JOIN rubrika AS r ON tr.ID_rubrika = r.ID
WHERE tr.ID_rubrika = 2 ORDER BY tr.ID_clanek DESC LIMIT 10 OFFSET 0

Tady tom Radim podle


Tady tom Radim podle ID_clanek, ale kdybych tě tabulce řazení přidal sloupec ID s autoincrement a radil bych ti podle toho nebylo by to rychlejší?


Ne Radim ale řadíme. Píšu to na mobilu a on my to pořád opravuje.
frgg
Profil *
popř. jak by jsi to napsal ty?
Keeehi
Profil
frgg:
Budu předpokládat, že tr a rr jsou jedno a to samé a jde jen pouze o překlep, jinak by ten dotaz nedával smysl.

Napsal bych to tak, že WHERE a ORDER BY by používaly sloupce z tabulek s daty, ne z vazební tabulky.
WHERE r.ID = 2 ORDER BY c.ID
Tam to jsou primární klíče a index nad nimi určitě bude.
frgg
Profil *
Keeehi:
Napsal bych to tak, že WHERE a ORDER BY by používaly sloupce z tabulek s daty, ne z vazební tabulky.
jestl ito tak je rychlejší. Ale je pravda žeinnodb si vede svoje vlastní ID když tam nic nedám?

Primárním klíčem můžou být oba sloupce dohromady - tedy složený klíč.
já vytvářím indexi na obou samostantně. když vyexportuju tu tabulku tak tam je toto:
CREATE TABLE `rubriky_razeni` (
  `ID_rubriky` bigint(20) UNSIGNED NOT NULL,
  `ID_clanku` bigint(20) UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

ALTER TABLE `rubriky_razeni`
  ADD KEY `ID_rubriky` (`ID_rubriky`),
  ADD KEY `ID_clanku` (`ID_clanku`);
tohle je teda ten složený klíč nebo to jsou dva samosttné?


složený by vypadal takhle.
ALTER TABLE `rubriky_razeni`
  ADD KEY `idobou` (`ID_rubriky`,`ID_clanku`);



Budu vypisovat články podle rubriky a při výpisu jednoho článku budu z tabulky zjisštovat id rubriky.
juriad
Profil
frgg:
Ano, vytváří si skrytý sloupec, pro své vlastní účely. To tě vůbec zajímat nemusí. Ty nepotřebuješ z databáze vyždímat poslední desetinky procenta.
blog.jcole.us/2013/05/02/how-does-innodb-behave-without-a-primary-key

Ano, vytvořil jsi dva indexy; ano složený index se dělá přesně tak.


Mějme tabulku se sloupci (X, Y).

Index na sloupci (X) zrychlí dotazy, které mají ve WHERE porovnání sloupce X s hodnotou (například X=5 nebo x>1500 AND X<2000), nezrychlí dotazy, které nefiltrují podle X.
Pokud pro každé X existuje hromada Y (příklad: uživatel (X) má oblíbemé články (Y)), tak může vyhledání, zda uživatel má oblíbený konkrétní článek pomalé (miliony oblíbených článků).
Přesně stejně to bude pro index (Y).

Složený index (X, Y) a tady záleží na pořadí(!) funguje jako index (X), ale umí urychlit i dotazy které obsahují podmínky na X i Y zároveň. Neurychlí dotazy, které filtrují jen podle Y.
Je tedy často dobrý nápad na vazebních tabulkách definovat dva indexy (X,Y) a (Y). Použití indexů (X) a (Y) je horší než předchozí možnost. Pokud chceš jen jeden index, dej si pozor na to, který bude jeho první sloupec (pokud je složený).
juriad
Profil
Pokud tě zajímá, jestli se nějaký index použil, použij EXPLAIN, ukáže ti prováděci plán dotazu.
dev.mysql.com/doc/refman/8.0/en/execution-plan-information.html
frgg
Profil *
takže pokud budu vytahovat články podle ID_rubriky a u výpisu jednoho konkrétního článku budu hledat podle ID_clanku, bude pro mě vhodnější nepoužívat složený klíč, ale lepší bude indexovat oba odděleně... je to tak?


tj takhle
ALTER TABLE `rubriky_razeni`
  ADD KEY `ID_rubriky` (`ID_rubriky`),
  ADD KEY `ID_clanku` (`ID_clanku`);
juriad
Profil
Ano, v tomto případě ti budou stačit dva jednoduché indexy. Uvidiš sám, jak se bude aplikace vyvíjet a jaké další dotazy budeš potřebovat; pak můžeš indexy změnit.
frgg
Profil *
ok, díky všem za rady.


to je snad všechno co sem potřeboval


vlastně ne


je tu ještě jedn a věc


a to je výpis všech článků.... napíšu to zjednodušené tj. nebudu vybírat rubriku a tagy...
SELECT c* 
FROM clanek AS c
ORDER BY c.ID DESC LIMIT 10

mám tabulku kde si uchovávám počet článků... pokud bych chtěl tedy vypsat posledních deset, nebylo by na výpočet lepší toto?
počet článku = 238;
SELECT c* 
FROM clanek AS c
ORDER BY c.ID DESC OFFSET 237 LIMIT 10

v tom prvním případě musí mysql vybrat všechny články a potom je seřadit podle id ale tady jen přeskakuje 237 řádků a seřazuje až těch posledních 10... nebo to vyjde nastejno?


*namísto 237 tam má být 227
juriad
Profil
Nepotřebuješ tabulku na počítání článků. SELECT COUNT(*) FROM clanek postačuje.

SELECT * FROM (
  SELECT c.* 
  FROM clanek AS c
  ORDER BY c.ID DESC
  LIMIT 10
) last10
ORDER BY ID ASC
Najde posledních 10 a pak je vrátí v pořadí od nejstaršího.
Keeehi
Profil
frgg:
tady jen přeskakuje 237 řádků a seřazuje až těch posledních 10... nebo to vyjde nastejno?
A jak by věděl, kterých 237 (opraveně 227) by měl přeskočit? Seřadí se všech 237 a pak se až vezme 10.

Jenže jelikož se řadí podle indexu, tak se vlastně nic řadit nemusí, jelikož už to seřazené je.

Trošku tu ale řešíš zbytečnosti. Dokud nebudeš mít trochu vyšší počet dat v databázi (třeba statisíce řádků) nejspíš vůbec nepoznáš rozdíl jestli tam indexy máš či ne.
frgg
Profil *
Keeehi:
A jak by věděl, kterých 237 (opraveně 227) by měl přeskočit? Seřadí se všech 237 a pak se až vezme 10.
jednoduše když když vytahuju články a nenapíšu tam podle čeho řadit tak to bere od ID 1 až po konec. takže 227 přeskočí, veme těch deset posledních a ty seřadí podle ID od největšího po nejmenší. Nebo to dělá jinak?

juriad:
SELECT COUNT(*) FROM clanek postačuje.
Ne úplně:
mysql> select count(*) from a_innodb;
+----------+
| count(*) |
+----------+
|  6291456 |
+----------+
1 row in set (2.16 sec)


A jak funguje tenhle select? vybírá všechny články tj, mojich 237 a pak vezme 10 posledních? nebo jde od posledního ID až po 227?
SELECT * FROM (
  SELECT c.* 
  FROM clanek AS c
  ORDER BY c.ID DESC
  LIMIT 10
) last10
ORDER BY ID ASC



(tamten můj příkaz sem měl trochu chybně... takhle to je
SELECT c.*
FROM clanek AS c
ORDER BY c.ID DESC LIMIT 10 OFFSET 5
)
ale ted když to zkouším... neděláte to co jsem já zamýšlel... :( ach jo :(


ufffff...


Keeehi:
Jenže jelikož se řadí podle indexu, tak se vlastně nic řadit nemusí, jelikož už to seřazené je.
takže i když tam mám nápsáno ORDER BY c.ID DESC, tak se ty čísla neřadí? jestli ne tak by to bylo ok...
Keeehi
Profil
frgg:
nenapíšu tam podle čeho řadit tak to bere od ID 1 až po konec.
To je jen náhoda*. Pokud v SQL dotazu není uvedeno ORDER BY není pořadí řádků zaručené. Může být naprosto libovolné.

* Kvůli indexu jsou řádky interně seřazené a nejjednodušší a nejrychlejší je prostě vrátit tak jak už jsou seřazené. Proto ti to řadí i bez explicitního uvedení ORDER BY. Ke to ale jen náhoda a nemůžeš se na to spolehnout.

Máš spoustu otázek které jdou velmi hluboko do fungování databází ale sám rozumíš sotva začátkům. Pokud tě to opravdu zajímá tak doporučuji začít studovat. Přečíst spoustu článků, dokumentaci MySQL atp.
Já sám mám za sebou dva vysokoškolské kurzy ohledně relačních databází. Jeden ohledně správného návrhu a tvorby databází a tabulek pro potřeby aplikace a druhý o interním fungování databází jako takových. Různé typy indexů, fyzické ukládání dat atd. A i když mi to hodně dalo vím že jsem spíše jen nahlédl na jen okraj.
frgg
Profil *
Keeehi:
Máš spoustu otázek které jdou velmi hluboko do fungování databází ale sám rozumíš sotva začátkům.
Já sám mám za sebou dva vysokoškolské kurzy ohledně relačních databází.... A i když mi to hodně dalo vím že jsem spíše jen nahlédl na jen okraj.
Uhhhmm... tady bude hlavní problém angličtina.... no dobře, tenhle nebo příští týden se moje stránka objeví v "názor na stránku".... snad to nebude tak špatný.
Moderátor juriad: Prosím nepoužívej mmm, toto slouží k přivolání moderátora

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: