Žádné ze dvou navržených řešení není pravděpodobně optimální, ALE řešení 1 je NEPŘEDPOVÍDAJÍCÍ, a proto JE VLASTNĚ VADNÉ!
Jedna z prvních věcí, které se naučíte při práci s velkými databázemi, je, že „nejlepší způsob“ zadání dotazu často závisí na faktorech (označovaných jako metadata) v databázi:
- Kolik je řádků.
- Kolik tabulek dotazujete.
- Velikost každého řádku.
Z tohoto důvodu je nepravděpodobné, že váš problém bude vyřešen. Vaše databáze není stejná jako moje databáze. Budete-li potřebovat nejlepší dostupný výkon, budete muset porovnat různé optimalizace.
Pravděpodobně zjistíte, že používání a vytváření správných indexů (a pochopení nativní implementace indexů v MySQL) ve vaší databázi pro vás udělá mnohem víc.
Existují některá zlatá pravidla pro dotazy, která by měla být zřídkakdy porušena:
- Nedělejte je ve cyklických strukturách . Jakkoli je to často lákavé, režie na vytvoření připojení, provedení dotazu a získání odpovědi je vysoká.
- Vyhněte se
SELECT *
pokud není potřeba . Výběr více sloupců výrazně zvýší režii vašich operací SQL. - Znáte své indexy . Použijte
EXPLAIN
Díky této funkci můžete vidět, které indexy se používají, optimalizovat své dotazy tak, aby využívaly dostupné možnosti, a vytvářet nové.
Z tohoto důvodu bych z těchto dvou šel pro druhý dotaz (nahrazením SELECT *
pouze s požadovanými sloupci), ale pravděpodobně existují lepší způsoby, jak strukturovat dotaz, pokud máte čas na optimalizaci.
Rychlost by však NEMĚLA buďte v tomto ohledu vaším jediným hlediskem, existuje VELKÝ důvod, proč nepoužít návrh jedna:
PŘEDVÍDATELNOST:proč jsou zámky čtení dobrá věc
Jedna z dalších odpovědí naznačuje, že mít tabulku uzamčenou na dlouhou dobu je špatná věc, a proto je řešení s více dotazy dobré.
Řekl bych, že to nemůže být dále od pravdy . Ve skutečnosti bych tvrdil, že v mnoha případech je předvídatelnost spuštění jediného zamykání SELECT
dotaz je větší argument PRO spuštění tohoto dotazu než výhody optimalizace a rychlosti.
Za prvé, když spustíme SELECT
(pouze pro čtení) dotaz na databázi MyISAM nebo InnoDB (výchozí systémy pro MySQL), stane se, že tabulka je uzamčena pro čtení. To zabrání tomu, aby na stole probíhaly jakékoli operace WRITE, dokud se zámek čtení nevzdá (buď naše SELECT
dotaz se dokončí nebo selže). Jiné SELECT
dotazy nejsou ovlivněny, takže pokud používáte vícevláknovou aplikaci, budou i nadále fungovat.
Toto zpoždění je DOBRÁ věc. Proč, můžete se zeptat? Relační integrita dat.
Vezměme si příklad:spouštíme operaci, abychom získali seznam položek aktuálně v inventáři mnoha uživatelů ve hře, takže se připojíme takto:
SELECT * FROM `users` JOIN `items` ON `users`.`id`=`items`.`inventory_id` WHERE `users`.`logged_in` = 1;
Co se stane, když během této operace dotazu uživatel vymění položku jinému uživateli? Pomocí tohoto dotazu vidíme stav hry, jaký byl, když jsme dotaz spustili:položka existuje jednou, v inventáři uživatele, který ji měl před spuštěním dotazu.
Co se ale stane, když to spustíme ve smyčce?
V závislosti na tom, zda s ní uživatel obchodoval předtím, nebo poté, co jsme si přečetli jeho údaje, a v jakém pořadí čteme inventář dvou hráčů, existují čtyři možnosti:
- Položka může být zobrazena v inventáři prvního uživatele (skenovat uživatele B -> skenovat uživatele A -> obchodovaná položka NEBO skenovat uživatele B -> skenovat uživatele A -> obchodovaná položka).
- Položka by mohla být zobrazena v inventáři druhého uživatele (obchodovaná položka -> skenování uživatele A -> skenování uživatele B NEBO obchodovaná položka -> skenování uživatele B -> skenování uživatele A).
- Položka může být zobrazena v obě inventáře (skenovat uživatele A -> obchodovaná položka -> skenovat uživatele B).
- Položka nemůže být zobrazena v žádném inventáře uživatele (skenovat uživatele B -> obchodovaná položka -> skenovat uživatele A).
To znamená, že nejsme schopni předvídat výsledky dotazu nebo zajistit relační integritu .
Pokud plánujete v úterý o půlnoci dát 5 000 $ muži s ID položky 1 000 000, doufám, že máte po ruce 10 000 $. Pokud váš program spoléhá na to, že jedinečné položky jsou při pořizování snímků jedinečné, možná u tohoto druhu dotazu vyvoláte výjimku.
Zamykání je dobré, protože zvyšuje předvídatelnost a chrání integritu výsledků.
Poznámka:Uzamčení smyčky můžete vynutit pomocí transakce , ale bude stále být pomalejší.
A nakonec POUŽÍVEJTE PŘIPRAVENÁ VÝKAZY!
Neměli byste nikdy mít výpis, který vypadá takto:
mysqli_query("SELECT * FROM Table2 WHERE ColumnAId=" . $row['ColumnAId'], $con);
mysqli
má podporu pro připravené výpisy
. Přečtěte si o nich a používejte je, pomohou vám vyhnout se něčemu hroznému, aby se vaší databázi nestalo
.