peter13135
1.09.2012, 09:34:14
Jak w temacie, w jaki sposób to zrobić ?
kod wygenerować potrafię, dodać go do bazy o dziwo też. Ale ponieważ tego ma być dokładnie milion, to dodanie tego w ten sposób:
$kod = generujKod();
$istnieje = sprawdzCzyKodIstniejeWBazie();
if($istnieje)
{
dodajKodDoBazy();
}
Moim zdaniem jest nieco kiepskim pomysłem.
Myślałem o tym, by generować powiedzmy 100 kodów i sprawdzać, które z nich istnieją, myślę,że takie hurtowe wysyłanie pójdzie nieco szybciej.
A co Wy proponujecie ?
zamper
1.09.2012, 10:02:50
A może tak:
$kod = sha1
( time().microtime().''.($jakasLosowaLiczba * $jakasInnaLosowaLiczba / $jakasJeszczeInnaLosowaLiczba) );
Potem to puszczasz w pętli która wstawia to do bazy

To co masz z funkcji hashującej możesz w dowolnej kolejności mieszać, a kody zawszę będą mieć 40 znaków i będę na 99.(9)% unikalne
peter13135
1.09.2012, 10:19:22
Pisałem, że kod potrafię wygenerować. I zrobię to innym sposobem (choćby dlatego, że chce mieć też duże znaki, których sha1 chyba nie posiada)
Problem jest w tym, żebby to wszystko wprowadzić do bazy.
Tablica w php chyba nie przetrzyma miliona rekordów (chyba, że się mylę);
zamper
1.09.2012, 10:22:48
Cytat
Potem to puszczasz w pętli która wstawia to do bazy
Albo możesz też zrobić zapytania typu:
INSERT INTO kody VALUES ('sfdwfw'), ('wfwfe'), ('wefegf');
Wazniak96
1.09.2012, 10:31:36
a myslales o przepuszczeniu tego przez pętle for i dodawac np po 10000 rekordow do bazy .?
peter13135
1.09.2012, 10:35:43
Cytat
INSERT INTO kody VALUES ('sfdwfw'), ('wfwfe'), ('wefegf');
Aby takie zapytanko wygenerować, musze mieć najpierw tablicę z tymi kodami.
Moja super maszyna za pomocą mojego super kodu w PHP, jest w stanie wygenerować jakieś 32k kodów w ciągu pierwszej minuty, zapisując je do tablicy i sprawdzając czy taki kod już istnieje. W kolejnych minuatach będzie pewnie trochę mniej generowanych kodów, bo sprawdzanie (za pomocą in_array) czy kod już istnieje będzie coraz wolniej działało wraz ze wzrostem elementów tablicy. Dlatego poszukuję lepszego rozwiązania.
Cytat
a myslales o przepuszczeniu tego przez pętle for i dodawac np po 10000 rekordow do bazy .?
Myślałem (przecież nawet o tym pisałem) ale wtedy musiałbym łączyć się z bazą i sprawdzać czy kod istnieje, co chyba trwa więcej niż sprawdzenie tego w tablicy php. Z drugiej strony, nie wiem czy jest możliwe utworzenie tak dużej tablicy
zamper
1.09.2012, 10:39:20
Jeżeli zależy ci na czasie to wymyśl taki algorytm tworzenie kodów, żeby się nie powtarzały.
Potem pętla na zasadzie takiej
$q = 'INSERT INTO kody VALUES ';
for($i=0; $i<1000000; $i++) {
$q .= '("'.generujKod().'"),';
}
$res = $db->query($q);
Do funkcji generujKod możesz przekazać licznik pętli i na podstawie jego utworzyć kod
peter13135
1.09.2012, 10:46:20
Niestety, takiego algorytmu stworzyć nie potrafię (który byłby nie do rozszyfrowania przy okazji)
zamper
1.09.2012, 10:50:07
Cytat
Pisałem, że kod potrafię wygenerować. I zrobię to innym sposobem (choćby dlatego, że chce mieć też duże znaki, których sha1 chyba nie posiada)
No to jak w końcu

Algorytm najlepiej zrób na podstawie
time,
microtime,
rand. Potem to wszystko opakuj w
sha1. Później możesz tego hasha przetransformować tak, żeby co losowo wygenerowany numerek (albo licznik pętli) robiło większą literę
peter13135
1.09.2012, 10:54:02
1.Pisałem, że potrafię wygenerować losowy ciąg znaków (co nazywałem kodem), a nie potafię stworzyć algorytmu do generowania kodów, które by się nie powtarzały.
2. A jak zagwarantujesz, że Twój sposób zwróci mi milion unikalnych kodów ? Pozatym, długość tego mojego kodu ma być równa 10.
Wazniak96
1.09.2012, 10:55:20
Kiedys na necie znalazlem taki oto kodzik do tworzenia kodow, moze Ci się kolego przyda
$letters = 'abcdefghijklmnopqrstuvwxyz';
$digits = '0123456789';
function password_letters($length) {
$array = str_split( $letters );
}
function password_digits($length) {
$array = str_split( $digits );
}
function password_combined($length) {
$array = str_split( $letters.$digits );
}
$haslo = password_combined(6);
peter13135
1.09.2012, 10:57:56
To spytam trochę inaczej. Mogę dać do tabeli w bazie klucz UNIQUE.
Czy jest możliwość, wykonania zapytania typu
[sql]INSERT INTO `codes` VALUES ('kod1'), ('jakiś inny kod'), (...)[/code]
Załóżmy, że ma on 10k kodów i jeśli powiedzmy powtórzy się 100 kodów, to zamiast errora "duplicate entry..." po prostu pominie te duplikaty i doda 9900 kodów ?

//edit:: już wiem

edit://
@up, dzięki za chęci, ale się nie przyda.
zamper
1.09.2012, 10:58:27
Mój mały algorytm tworzy co prawda 40 znakowe kody, ale na pewno będę one unikalne, bo są zależne od czasu i kilku liczb losowych oraz ewentualnie licznika pętli
Co do tego, żeby kody miały tylko 10 znaków to już trudniejsza sprawa, ale jeżeli mają one być do potwierdzenia rejestracji konta to 40 a 10 znaków nie robi takiej różnicy, bo i tak kod jest wklepany w linku
peter13135
1.09.2012, 11:00:02
Nie mają być do potwierdzenia rejestracji konta, uwierz mi, że do tego celu nie potrzebował bym generować tyle kodów jednocześnie.
zamper
1.09.2012, 11:10:21
Możesz w takim razie utworzyć zmienną zawierającą wszystkie znaki dostępne w kodzie (a-z A-Z 0-9) i w pętli 10 razy za pomocą liczby losowanej w każdej iteracji wyciągać jakiś znak w tej zmiennej. Wadą tego rozwiązania jest możliwość powtórzenia się kodów.
Kużdo
1.09.2012, 11:19:46
Ale kombinujecie. Tworzysz unikalną kolumnę w bazie, a przy wrzucaniu swoich rekordów ignorujesz duplikaty w sposób:
INSERT IGNORE INTO `nazwa_tabeli` ...
A najlepiej jakbyś zrobił sobie formularz do wpisania ilości generowanych rekordów, bo przyda się później. Pod koniec skryptu pobierasz ilość wszystkich rekordów:
SELECT COUNT(`id`) AS `ile` FROM `nazwa_tabeli`
i wyświetlasz sobie ile masz już rekordów, dzięki temu będziesz wiedział ile wpisać w pole formularza jeszcze.
peter13135
1.09.2012, 11:25:10
Drogi Kolego zamper. Pisałem w pierwszym poście, o tym że jestem w stanie wygenerować sobie kod (w którymś z następnych postów dodałem, że ma mieć 10 znaków). I z mojego pierwszego postu wynika, że aby utworzyć za pomocą mojego sposobu milion unikalnyh kodów, muszę za każdym razem sprawdzać, czy wcześniej takiego kodu nie wygenerowałem. Zauważ więc, że Twój post nic nowego nie wnosi do tematu.
Zrobiłem kod, który generuje 1000 kodów, następnie wrzuca je do bazy, a baza danych zapisuje tylko te, których jeszcze nie ma w bazie (za pomocą INSERT IGNORE). Działąło by super.... tylko, że baza danych przyjmuje tylko 32768 rekordów. Czy jest na to jakiś sposób ?
@up. O tym, że dowiedziałem się, że jest coś takiego jak INSERT IGNORE dowiedziałęm się jakieś 20 minut temu (patrz post nr 12)
dr_NO
1.09.2012, 11:30:13
Za MySQL Change Log
Cytat
Support for large databases. We use MySQL Server with databases that contain 50 million records. We also know of users who use MySQL Server with 200,000 tables and about 5,000,000,000 rows.
Jakiego typu masz pola w bazie? Może używasz typu który ma ograniczenia?
Kużdo
1.09.2012, 11:31:54
Nie zauważyłem tego

Przyjmuje Ci MAKS 32768 rekordów, czy w jednej paczce tyle? Bo nie do końca zrozumiałem to co napisałeś. Miałem w sumie wrzucić tutaj przykładowy kod do poprzedniego postu, ale nie wiem czy jest Ci jeszcze potrzebny.
peter13135
1.09.2012, 11:32:59
id to big int
typ bazy to MyIsam, przed chwilą miałem innoDb, ale na obu mam ten limit.
Paczki mam po 10k
Baza ma limit ~33k (2^15)
Kużdo
1.09.2012, 11:35:26
Nie wiem co to za limit, ja mam testową tabelę z polami id(unsigned int) i kod(varchar:10) i mam już ponad 500 tys. rekordów.
peter13135
1.09.2012, 11:36:05
a jaki typ bazy danych ? (jak robię nową bazę to mam "mechanizm składowania"
Kużdo
1.09.2012, 11:36:43
InnoDB
dr_NO
1.09.2012, 11:38:48
Ograniczenia serwera? Gdzie testujesz?
Cytat
bigint largest value is 18,446,744,073,709,551,615
peter13135
1.09.2012, 11:51:18
testuje na localu. Jakimś cudem udało mi się upchać ~83 k rekordów. (tzn. jak sortuję po id DESC, to największe id to właśnie koło 83k)
Takie zapytanko
SELECT count( id )
FROM `codes`
Pokazuje mi jednak 32768
Wszystko testuje na swoim localu najnowszy xampp (tzn. najnowszy był jak go ssałem

) + windows xp sp3
Kużdo
1.09.2012, 11:57:52
Spróbuj tego (chociaż nie wiem co za różnica, ale może coś źle robisz):
CREATE TABLE IF NOT EXISTS `kody` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`kod` varchar(10) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `kod` (`kod`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
W core.php połączenie z bazą etc.
<form action="" method="post">
<input type="text" name="ile" /> <input type="submit" value="ok" />
</form>
<?php
{
require_once 'core.php';
$query = "INSERT IGNORE INTO `kody` (`kod`) VALUES ";
for($i = 0; $i < $_POST['ile']; $i++)
{
}
$query = trim($query, ', ');
$query .= ';';
$ile = "SELECT COUNT(`id`) as `ile` FROM `kody`";
echo '<br /><br />W bazie jest juz: '.$ile['ile'].' rekordow.'; }
?>
peter13135
1.09.2012, 12:12:43
yeah, udało się

Taka funkcja
function generujKod()
{
$str = '';
for($i =0; $i<10; $i++)
{
$str.= $this->chars[rand(0
,57
)]; }
{
$this->codes[] = $str;
}
}
Generowała ~16k unikalnych znaków, więcej nie chciała.
funkcję rand() zamieniłem na
I teraz jest gites, dociągnąłem do miliona
Kużdo
1.09.2012, 12:14:53
A po co w tym masz jeszcze sprawdzanie czy w tablicy znajdują się już takie wartości? Pisałem o tym wcześniej i też w moim przykładzie nigdzie nie używam tablic, a to dlatego, że robisz bezsensowną pracę. Masz nałożone UNIQUE w tabli, więc sprawdzanie tablicy po stronie PHP już nie jest potrzebne.
peter13135
1.09.2012, 12:16:40
Ponieważ na początku przjąłem inną koncepcję (tzn. wygenerowanie kodów wszystkich i następnie ich załadowanie) potem się to zmieniło, a kod został. To wielkiego znaczenia nie ma, bo wygenerowaie tych kodów miałó być jednorazowe.
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.