Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Update miliona rekordów
Forum PHP.pl > Forum > PHP
infor946
Mam 2 tabele, w jednej jest lista tytułów i słowa kluczowe w jezyku ang.
Słowa kluczowe oddzielone są przecinkami i ich liczba dla poszczególnych rekordów jest zmienna. Liczba rekordów w tej tabeli to prawie 1 milion.

Druga tabelka zawiera listę wszystkich użytych keywordów angielskich i odpowiadające im polskie tłumaczenie. Około 40 tyś unikalnych rekordów.

Chciałbym teraz przetłumaczyć tzn zamienić wszystkie słowa angielskie w tabeli z milionem rekordów na polskie, ale nie wiem jak sie za to wogóle zabrać, czy da sie to potraktowaćjakimś skryptem, który przetłumaczyłby (pozamieniał) na raz, czy trzeba to robić etapami (ile) ?
chomiczek
sądze, ze dałoby sie chyba zrobić w jednym skrypcie (bez podziału na etapy).
Mysle, ze można by dodać jedno pole do tabeli (np. zrobione), w którym przechowywałbyś 0 i 1 (jedynka oznaczałaby np to, ze pole już zostało zmienione) w przypadku kiedy skrypt by sie przerwał, albo wystąpiłby jakis bład to update nie szedłby od początku przy następnym wywołaniu skryptu, ale wykonywany byłby dla tych pozycji , które nie miały update. Dodatkowo ustaw sobie na początku
  1. <?php
  2. ?>

dzięki czemu skrypt będzie się wykonywał do zakończenia.

Sugerowałbym tez przy testach zapytań, albo nie wykonywania ich tylko wyświetlenie, a także ustawienie limitu np. 10rekordów, zeby sprawdzac czy wszystko jest ok.. dla swietgo spokoju proponowalbym zrobic kopie bazy.

Na zakończenie wrzuc jakis listing.. moze komuś sie przyda
infor946
  1. <?php
  2. $link = mysql_pconnect("127.0.0.1", "root", "")
  3.  or die ("Nie można się połączyć");
  4. print ("Połączenie nawiązane<BR>");
  5. mysql_select_db ("voluminy") or die ("Nie mozna wybrać bazy danych");
  6. $query="select id, keywords from tabela where translated=0";
  7. $source=mysql_query($query);
  8. while($english=mysql_fetch_array($source, MYSQL_ASSOC))
  9. {
  10. $keywords=$english['keywords'].",";
  11. $wyst=substr_count($keywords,",");
  12. $key="";
  13. for($i=0;$i<$wyst;$i++)
  14. {
  15. $pozycja=strpos($keywords, ",");
  16. $tab_org[$i]=substr($keywords,0,$pozycja);
  17. $query2 = "SELECT english, polish FROM slownik where english like '$tab_org[$i]'";
  18. $tlumaczenie = mysql_query ($query2);
  19. if($wyr_tlum=mysql_fetch_array($tlumaczenie, MYSQL_ASSOC))
  20. {
  21. $key=$key.$wyr_tlum['polish'].",";
  22. }
  23. else
  24. {
  25. $key=$key.$tab_org[$i].",";
  26. }
  27. $keywords=substr($keywords, $pozycja+1, strlen($keywords)-$pozycja);
  28. }
  29.  
  30. $sqlu="update tabela set keywords = '".$key."', translated = 1 where id = '".$english['id']."'";
  31. mysql_query($sqlu);
  32. }
  33. print "gotowe"
  34. ?>


To działa, ale bardzo wolno, tłumaczy jakieś 100 rekordów na min, co przy 1mil rekordów trwaoby 7 dni exclamation.gif!!!, nie da sie tego zrobić w jakiś inny sposób żeby było szybciej ?
lisu
na poczatek poczytaj manuale funkcji implode i explode
co sadzicie aby rozbic te milionowa tablice, tak by jeden tytul mial jednego keyworda w rekordzie i pozniej zapytaniem sql to podmienic i spowrotem zlaczyc CONCAT'em.

Albo II koncepcja smile.gif bo wlasnie jeszcze zajrzalem tutaj: mysql i moze warto sie zainteresowac: FIND_IN_SET(str,strlist):
....string list strlist consisting of N substrings. A string list is a string composed of substrings separated by ‘,’ characters..... czyli oddzielane przecinkiem.

jest i nawet SUBSTRING smile.gif
dr_bonzo
A jesli by znormalizowac baze danych, utworzyc takie tabele

ksiazki (czy co to ma byc?)
ID (PK) | tytul

slowa_kluczowe
ID (PK) | slowo_eng | slowo_pl

ksiazki_slowa_kluczowe (do utworzenia relacji wiele-do-wielu)
ksiazka_id(FK) | slowo_kluczowe_id (FK)

1. tabele slowa_kluczowe (jak napisales) juz masz, ladujesz ja do pamieci php tak aby odwolywac sie do niej:

$slowo_kluczowe[ 'angielska_nazwa' ][ 'polskie_tlumaczenie']
i
$slowo_kluczowe[ 'angielska_nazwa' ][ 'ID']

oszczedzasz mnostwo zapytan do bazy po pojedyncze rekordy, a w pamieci zajmie ci to powiedzmy 40.000 x 50B (/slowo) = 2MB -- tyle co nic smile.gif


2. tabela ksiazki (albo to cos z tytulem)
lepiej utworzyc nowa tabele (i pozostawic ta stara z ID | tytul | slowo; slowo2; itd)

* Odczytujesz jeden rekord ze swojej tabeli, wyciagasz z niego tytul, a slowa kluczowe rozbijasz explode.
* Wstawiasz rekord do tabeli ksiazki i pobierasz, ID ktore zostalo wstawione (mysql_inserted_id)
* dla kazdego slowa kluczowego dla tego rekordu pobierasz jego tlumaczenie i ID w bazie
* do tabeli ksiazki_slowa_kluczowe dla kazdego ze slow kluczowych wstawiasz rekord (id_ksiazki, id_slowa_kluczowego)

3. jesli potrzebujesz zachowac poprzednia strukture bazy (zdenormalizowana) mozesz to zrobic



Mozesz tez tylko uzyc cachowania tlumaczen slow kluczowych (patrz p. 1) -- z tym ze pomijasz pobieranie ID.


Zbadaj (zmierz microtime() co zajmuje najwiecej czasu -- wyciaganie tlumaczen slow, dzielenie pola ze slowami kluczowymi na pojedyncze slowa, itd)

PS. Jak masz taka mozliwosci to zapusc swoj skrypt (na te 7 dni) a w miedzy czasie szukaj lepszego rozwiazania
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.