sql >> Databáze >  >> RDS >> Oracle

Vícevláknové čtení databáze

Síť

Za prvé, protože používáte rowid a rownum je vendor-lock tak jako tak, měli byste zvážit použití rutin uložených v databázi. Mohlo by to výrazně snížit režii přenosu dat z databáze na aplikační server (zejména pokud jsou na různých počítačích a připojeny přes síť).

Vzhledem k tomu, že máte k přenosu 80 milionů záznamů, mohlo by to být pro vás nejlepší zvýšení výkonu, i když to závisí na druhu práce, kterou vaše vlákna vykonávají.

Je zřejmé, že zvýšení šířky pásma by také pomohlo vyřešit problémy se sítí.

Výkon disku

Před provedením změn v kódu zkontrolujte zatížení pevného disku za běhu úloh, možná jen nezvládne tolik I/O (10 vláken současně čte).

Problém může vyřešit migrace na SSD/RAID nebo clusteringovou databázi. Při změně způsobu přístupu k databázi v tomto případě nikoli.

Multithreading by mohl vyřešit problémy s CPU, ale databáze většinou závisí na systému disku.

Rownum

Existuje několik problémů, kterým můžete čelit, pokud jej budete implementovat pomocí rowid a rownum.

1) rownum se generuje za běhu pro výsledky každého dotazu. Pokud tedy dotaz nemá explicitní řazení a je možné, že některé záznamy budou mít při každém spuštění dotazu jiné rownum.

Například jej spustíte poprvé a získáte výsledky jako tento:

some_column | rownum
____________|________
     A      |    1
     B      |    2
     C      |    3

pak jej spustíte podruhé, protože nemáte explicitní řazení, dbms (z nějakého známého důvodu) se rozhodne vrátit výsledky takto:

some_column | rownum
____________|________
     C      |    1
     A      |    2
     B      |    3

2) z bodu 1 také vyplývá, že pokud budete filtrovat výsledky podle rownum vygeneruje dočasnou tabulku s ALL výsledky a poté jej filtrovat

Takže rownum není dobrou volbou pro výsledky dělení. Zatímco rowid zdálo se to lepší, má také nějaké problémy.

Řádek

Pokud se podíváte na popis ROWID můžete si všimnout, že „hodnota rowid jednoznačně identifikuje řádek v databázi ".

."

Kvůli tomu a skutečnosti, že když smažete řádek, máte „díru“ v posloupnosti rowid, rowids nemusí být mezi záznamy tabulky rozděleny rovnoměrně.

Takže například pokud máte tři vlákna a každé načítá 1 000 000 rowidů, je možné, že jedno získá 1 000 000 záznamů a další dvě každý 1 záznam. Takže jeden bude přemožen, zatímco další dva hladoví .

Ve vašem případě to nemusí být velký problém, i když to může být problém, kterému v současnosti čelíte se vzorem primárního klíče.

Nebo pokud nejprve načtete všechny rowids v dispečeru a pak je rozdělíte rovným dílem (jak navrhoval peter.petrov), což by to mohlo udělat, ačkoli načtení 80 milionů ID stále zní jako hodně, myslím, že by bylo lepší provést rozdělení s jedním sql-query, který vrací hranice bloků.

Nebo můžete tento problém vyřešit tím, že dáte malý počet rowidů na úlohu a použijete rámec Fork-Join představený v Javě 7, nicméně to by měl být použito opatrně .

Také zřejmý bod:rownum i rowid nelze přenášet mezi databázemi.

Je tedy mnohem lepší mít svůj vlastní "sharding" sloupec, ale pak se budete muset ujistit, že rozděluje záznamy na víceméně stejné části.

Také mějte na paměti, že pokud to budete dělat v několika vláknech, je důležité zkontrolovat, co databáze v režimu zamykání používá , možná to jen uzamkne tabulku pro každý přístup, pak je multithreading zbytečný.

Jak navrhovali jiní, raději nejprve zjistěte, co je hlavním důvodem nízkého výkonu (síť, disk, zamykání databáze, hladovění vláken nebo možná máte jen neoptimální dotazy – zkontrolujte plány dotazů).



  1. Vložte div do kostky MYSQL

  2. jak umožnit přihlášeným uživatelům AKTUALIZOVAT / UPRAVOVAT nastavení/informace profilu

  3. Nelze znovu deklarovat dříve deklarovanou funkci

  4. Kontrola prázdného výsledku (PHP, PDO a MySQL)