[ S A J A @ 18.04.2021. 12:07 ] @
Zdravo svima,


Često imam potrebe da pravim tabele gde će primarni ključ biti vidljiv spolja pa nije baš dobro da to bude klasičan auto-increment ID. Razmišljam da to bude neki pseudo-string od 12 karaktera (npr: a99d680e12e6) pa me zanima da li će to da obori performanse kod pretraga? Konketno, da li je i koliko sporiji indeks za CHAR(12) u odnosu na INT?

[ dejanet @ 18.04.2021. 14:43 ] @
Mislim da PK, ne treba da bude vidljiv spolja ni u jednoj varijanti.
Ako mora, moze da bude enkriptovan, npr. ako ulazi kao url parametar.
[ Predrag Supurovic @ 18.04.2021. 14:57 ] @
Slažem se sa dejanetom. Primarni ključ treba da služi da jedinstveno identifikuje slog u tabeli.
Ako ti treba da ima neku drugu svrhu onda uvedi prirodni ključ pore PK i koristi prirodni ključ za tu drugu svrhu.


[ S A J A @ 18.04.2021. 15:05 ] @
Šta bi konkretno dobio time što bih imao dva identifikatora, jedan public jedan private?
[ djoka_l @ 18.04.2021. 15:41 ] @
Šta bi konkretno dobio ako PK nije int nego char?

Prvo osnovno razmatranje: poređenje dva int broja je jedna mašinska operacija. Ako uzmemo da su registri 64-bitni, poređenje 2 stringa dužine 12 su dve komparacija + još jedno grananje - znači 2 operacije viška.
U tabeli sa milion slogova, to znači da ćeš PK koji je int naći posle 20 komparacija, a char(12) posle 40.
To čak nije ni preterano bitno, bitnije je što ćeš morati da pročitaš, možda, 20 blokova iz baze koji sadrže indeks, tako da je broj komparacija nebitan u odnosu na I/O, pogotovo što će neki blokovi biti baferisani.

Indeks nad char(12) će zauzimati do 33% više prostora na disku.

Sve u svemu, neku razliku u pretraživanju nećeš videti, ako tražiš slog sa tačno specificiranom vrednošću polja koje je PK.

Ono što možeš da dobiješ kao poboljšanje je pretraživanje po prefiksu indeksa, recimo LIKE 'abc%' gde će char(12) ubedljivo da pobedi int PK.
Samo što je takvo pretraživanje besmisleno za PK, koji samo treba da bude jedinstvena oznaka sloga, a ne nešto što ima strukturu i neko "dublje" značenje.


Ako je tebi problem to što ne želiš da ti slogovi imaju sekvencu koja može da se pogodi, nemoj da PK bude nešto što ćeš da koristiš za takve stvari.
Recimo, broj kartice (kreditne ili debitne) je 16-cifreni broj, prvih 6 cifara je oznaka banke i tipa kartice, poslednja 2 su kontrolni brojevi.
Ono što je bitno za kartice je da onih srednjih osam ne idu u sekvenci, jer, recimo, ako posle kartice sa brojem 1, a koja važi do marta 2023, izdaš karticu broj 2, malčiciozni softver bi mogao da pretpostavi da je i rok važenja kartice 2 do marta ili aprila 2023. godine. Međutim, broj kartice ni kod jedne normalne banke nije PK.
[ dejanet @ 18.04.2021. 16:14 ] @
@S A J A:

Sto se mog odgovora gore tice, evo sta sam mislio, sta god da se izabere kao PK, pod uslovom da je moranje, kod requesta (ruta, url kod api, web ili mq), pre requesta enkriptovati, pa dekriptovati kod implementacije.
Kod vracanja rezultata, sta god bilo, npr. json, ako je nephodan PK, opet ga enkriptovati... Rezultat toga je da uvek imas enkriptovan pkid na klijentu, a po potrebi dekriptovan PK na server-u za potrebe query-ija.

Daleko od toga da je ovo najbolje resenje, ali je mislim najjednostavnije.
[ Branimir Maksimovic @ 18.04.2021. 16:43 ] @
Primarni kljuc string tipa ima smisla ako ima nekog smisla uzeti takav kljuc. Inace idjevi se u relacionim tabelama koriste kao pointeri na druge slogove. Mislim ono treba se smarati pa generisati ako nije prosti
auto inkrement.
[ nkrgovic @ 18.04.2021. 16:52 ] @
Moze li posasnjenje zasto PK ide van baze? Znam za bar jedam primer u mysql-u PK-a koji nije enkriptovan i ide van (tabela mysql.user ima kompozitni privatni kljuc od dva polja - user i host), ali me zanima use case da taj kljuc ide van.

Vodite racuna da je npr. uuid u biti 128-bitni integer, pre nego sto krenete da "zamisljate" char-ove. Ako vam se ne svidja da bude autoincrement INT, mozete da koristite uuid on je zamisljen za to da bude unique id.

Takodje, kako tacno treba da izgleda struktura tabele da id bude nesto sto treba kriptovati? Opet, cisto me zanima...

Tesko je dati odgovor na pitanje "kako da izvedem ovo", ako ne razumes cemu to sluzi ;)
[ Branimir Maksimovic @ 18.04.2021. 17:12 ] @
Kljuc ako se prikazuje ne steti osim ako se ne koristi za sql injection :P
no uglavnom select * from users razbije vecinu sajtova ;)
[ S A J A @ 18.04.2021. 17:16 ] @
Hvala svima na odgovorima, malo smo skrenuli sa teme koja je u osnovi razlika u brzini između indeksiranje INT i CHAR(12) pa smo prešli na usecase...

Probaću da objasnim. U pitanju je web aplikacija za poslovanje (knjigovodstvo i tako te stvari...). I tu postoje razne tabele tipa artikli, partneri, fakture, projekti i štošta drugo...
I recimo, jedna od tabela će biti firma. Znači korisnik kad se uloguje, moći će da otvori firmu (ili više firmi) pa da radi u njima.
Logično u bazi će biti tabela firmi i svaki put kad korisnik napravi neku akciju, uz podatke će morati da ide i ID firme kako bi znao na koju se odnosi.

Na primer: hoće da izlista artikle ili upiše fakturu, mora serveru da prosledi ID firme...
I sad, pošto je tabela firmi zajednička za sve korisnike, malo je glupo da oni kako otvaraju firme dobijaju ID koji je broj 1, 2, 3...

Zato sam i mislio da ID bude neki bezveze string koji nema nikakvo značenje, na primer: 14dda8872b0e, koji bi postavio kao primarni ključ u toj tabeli.
Taj broj generišem preko PHP funkcije bin2hex(openssl_random_pseudo_bytes(6)) i trebalo bi da je solidno jedinstven. Čak i ako dođe do dupliranja i baza odbije insert, ponoviću generisanje i upis i to neće biti problem. Takođe, tako generisan broj ima 4738381338321616896 kombinacija što je više nego dovoljno, zapravo čak i dosta više nego što ima INT. To meni vrši posao.

Tako da, ako već klijent dobija taj ID firme koji posle mora da prosledi u svakom zahtevu, zašto bi onda u bazi imao još jedan ID broj koji bi bio INT i koji nikad ne bi koristio?

[ dusans @ 18.04.2021. 18:53 ] @
uniqueidentifier (uuid, guid) ume da bude zahvalan pogotovo kada dođeš u situaciju
da seliš podatke iz jedne u drugu bazu, deliš između sistema, da dozvoliš klijentima da oni dodele id,
da generišeš id pre nego što dođeš do baze, itd... što uopšte nije retkost u praksi.
Prilično su non-guessable, svaka moguća platforma ume da ih generiše, itd...

Jesu nešto sporiji od int-ova ali imaju i svoje prednosti.
Pogotovo vs auto increment gde ne možeš da barataš sa id-em pre nego što si zaista uradio insert u db-u.

Za male tabele (tipa enum i slično) koristim prirodne ključeve (string).
Za radne podatke, ranije int, skorije gotovo svuda uniqueidentifier.
[ nkrgovic @ 18.04.2021. 19:15 ] @
OK, ajde ovako: Imaces, kao ID firme, da budemo optimisti, maksimalno sto hiljada slogova.

Stavi uuid, da te ne boli glava oko toga sta ce da bude. Ne izmisljaj toplu vodu kad postoji standard za to. :) Alternativno, ako zelis da imas jednosmernu vezu SHA224("ime_firme"). Performanse na tom broju slogova ti nece biti problem...
[ vujkev @ 18.04.2021. 21:04 ] @
Citat:
S A J A:
I sad, pošto je tabela firmi zajednička za sve korisnike, malo je glupo da oni kako otvaraju firme dobijaju ID koji je broj 1, 2, 3...


Što je glupo? Svaki korisnik će imati valjda neka određena prava nad svakom firmom i to što zna da postoji ID firme "1" mu ništa ne znači. Valjda ne zasnivaš logiku na tome da je jedina zaštita da korisnik ne zna ID firme.
[ BuzzLightyear @ 18.04.2021. 22:41 ] @
Citat:
S A J A:
Šta bi konkretno dobio time što bih imao dva identifikatora, jedan public jedan private?


U većini slučajeva trebalo bi da imaš autoinkrement primarni ključ i jednu (ili više) unique kolona. Ako nemaš nijednu unique kolonu, onda verovatno nešto nije u redu. Ovde je pitanje zašto bi imao dva veštačka ključa? Dovoljno je da imaš samo autoinkrement.
[ S A J A @ 19.04.2021. 00:44 ] @
Citat:
dusans:
uniqueidentifier (uuid, guid) ume da bude zahvalan...


Citat:
nkrgovic:
Stavi uuid, da te ne boli glava oko toga sta ce da bude.


Da, ovo je zapravo neka varijanta uuid-a, samo sam ga "skratio" na 12 karaktera. Mislim da je uuid 32 karaktera bez crtica, to mi deluje nekako mnogo.

Sad je sledeće pitanje, koliko je sporiji indeks CHAR(32) u odnosu na CHAR(12)? ;)

[ Shadowed @ 19.04.2021. 01:23 ] @
UUID je binary(16), ne char(32).
[ Predrag Supurovic @ 19.04.2021. 01:25 ] @
Citat:
S A J A:
Šta bi konkretno dobio time što bih imao dva identifikatora, jedan public jedan private?


Pogrešno si to razumeo. Nije jedan privatni a jedan javni. Nego je jedan primarni ključ (PK) a jedan je prirodni ključ.

Tehnički gledano definišu se isto: radi se o vrednosti koja mora biti jedinstvena na nivou tabele.

Razlika je u tome što primarni ključ nema i ne sme da ima ama baš nikakvo značenje osim da služi da se identifikuje slog u tabeli i njega određuje sama baza u trenutku kreiranja sloga.

Onog trenutka kada ti zatreba da primarni ključ upotrebiš tako da ima neko značenje to znači da ne treba njega da koristiš nego da uvedeš prirodni ključ. Prirodni ključ je nešto što određuje korisnik baze, bilo tako što ga sam ukucava u bazu ili tako što određuje pravila za nekakvo automatsko generisanje. To se može razlikovati od korisnika do korisnika. Prirodni ključ ima i prednost da njega ne koristiš za povezivanje sa drugim tabelema pa to znači da možeš u bilo kom trenutku da ga promeniš na slogu sve dok je i dalje jedinstven na nivou tabele.

Dobar primer su baš primeri koje si pomenuo: šifarnici komitenata, artikala, radnika i slično. Šifra komitenta, šifra artikla, šifra radnika, to su ključevi koji za korisnika baze mogu i obično i imaju značenje i on ih određuje te su to prirodni ključevi i to ne treba da budu ujedno i primarni ključevi.

Sasvim je realna situacija da korisnik baze u nekom trenutku odluči da promeni način šifrovanja u tabelama u želi da promeni šifre komitenata, šifre artikala, čifre radnika (s obzirom da su to vrednosti koje imaju zančenje on prosto zaključi da mu treba da preorganizuje šifre jer je zaključio da mu postojeća organizacija ne odgovara). To je prilično čest zahtev. Ako su te šifre ujedno i primarni ključevi u nebranom si grožđu jer su ti po njima povezani podaci u raznim drugim povezanim tabelama i menjanje šifre u osnovnom šifarniku znači da to mora da se menja svugde gde se ta šifra koristi. Verovatno to ne bi poželeo ni najcrnjem neprijatelju.

Drugi čest slučaj je da treba da se napravi novi slog za neki entitet ali još uvek nije određena značenjska šifra za entitet. Na primer, na web sajtu se prijavi novu kupac, web sajt prikupi njegove podatke i kreira ga u svom šifarniku kupaca. Onda pošalje te podatke u centralu gde u centralnom šifarniku takođe treba da se kreira taj novi kupac. Tek u centralnom šifarniku se dodeljuje šifra tom novom kupcu. Ako koristiš prirodni ključ kao primarni (šifru kupca), imaš problem jer da bi napravio slog mora da mu se odmah dodeli primarni ključ a ti ga nemaš. Ako je PK beznačenjski možeš odmah da ga dodeliš slogu (autoinkrement na primer) a prirodni ključ može da se dodeli i naknadno.

Slično je, recimo, sa artiklima - zamisli da od dobavljača stigne pun kamion raznorazne robe. Podatke o artiklima imaš ali su šifre artikala šifre koje je odredio dobavljaš, i po pravilu te šifre ti ne možeš da korsitiš nego dodeljuješ svoje. Neke artikle si možda već dobijao ranije pa ih imaš šifrirane ali neke ne. Nema se vremena da se u momentu prijema robe radi i šifriranje (a pošto robu primaju magacioneri oni i ne znaju kako da rade šifriranje) nego se roba prima i umese u bazu sa podacima koji postoje (koristeći beznačenjski primarni ključ za identifikaciju sloga) a tek se naknadno radi šifriranje te robe to jest dodeljuju joj se sopstvene šifre i to se upisuje kao prirodni ključ.

Treći slučaj je autoamtsko generisanje brojeva dokumenata, faktura, opremnica, ranih naloga, ulaza i izlaza magacina i čega sve ne. Brojevi dokumenata se po pravilu određuju po nekoj logici, i to nisu samo proste jednoznačne oznake. Neka vrsta dokumenta može da se kreira na više fizičkih mesta i pri tom, ne mora d azbači da sv amesta imaju uvek pristup centrlanoj bazi nego svako radi sa nekom svojom lokalnom bazom a povremeno radi sinhronizaciju. I sad, kako jedno mesto da dodeli broj dokumenta ako je taj dokument primarni ključ? Nije neizvodivo ali je komplikovano. Ako imaš pored PK i prirodni ključ, koji ćeš PK dodeliti je nebitno,jer je on interni, ali zato prirodni ključ možeš da dodeliš po nekom pravilu, recimo da uvedeš prefiks u broju dokumentakoji određuje loakciju na kojoj je dokument napravljen i tako obezbediš da broj dokumenta bude jedinsten na nivou centralne baze jer svaka će lokacija da koristi svoj jedinstveni prefiks.

U bazi gde su primarni i priodni ključevi odvojeni korisnik baze i ne mora uopšte da vidi i zna za primarne ključeve. On radi sa prirodnjim ključevima koji su njemu bitni i imaju neko značenje. Primarni ključevi su mu obično nepraktični jer su predugi. Zamsili nekoga ko radi sa redom veličine 1000 komitenata a mora da brata sa šiframa dugim 12, 16, 32 ili 64 znaka, zavisi koliko izabereš za primarni ključ. U praksi su mu dovoljna četri znaka. Ili zamisli tek nekoga ko iam hilajde artikala u ifarniku artikaal koji umesto da tim artiklim da neke smislene šifre koje je lako praktično koristiti na kasama, i još koje mogu da imaju neku značenjsku strukturu radi lakše pretrage artikala na kasama, oni moraju da koriste opet neke šifre od 12, 16, 32 ili 64 znaka koje su samo gomila brojeva i slova bez ikakve logike. A njemu je itekako bitna logika u šiframa.

Sve u svemu, kada razdvojiš primarni od pirodnog ključa, trsiš se mnogih problema koji bi te, inače, sačekali i po pravilu te skupo koštali jer ih ne bi predvideo na vreme.


Što se tiče samog primarnog ključa, obuično nema potrebe da uopšte nešto izmišjaš nego korsitiš autoinkrement ceo broj i to je to. Korišćenje karakterinog polja za priamrniključ obično iam smisle tak ako imaš potrebu da ipak daš neko značenje sadržaju priamrnog ključa, ali ne ono koje mu daje korisnik baze nego nešto što ima logoku za tovju apliakciju. Na primer možeš u primarnom ključu kao prefiks da koristiš poslovnu godinu i tako omogućiš fizičko segmentiranje tabele po tom prefiksu, što može znatno da ubrza pristup podacima.

[Ovu poruku je menjao Predrag Supurovic dana 19.04.2021. u 02:50 GMT+1]
[ bogdan.kecman @ 19.04.2021. 04:31 ] @
Citat:
Shadowed:
UUID je binary(16), ne char(32).


128 bita tj 16 bajtova ... sve je to super samo mysql nema uuid funkcije pre 8.0, ma koliko ja savetujem svima da predju na 8.0 i dalje oko 50% raje koristi verzije starije od 8.0

uuid kao pk realno nema prednost, znam da ce sada iljade ljudi da skoci u odbranu uuid-a ali zao mi je to je istina, to je samo jedan veliki hype ..

osnovne prednosti uuid-a koje se pedlaju svuda vec deceniju su
[1] unique values across tables/databases/servers ...
[2] do not expose data
[3] can be generated on the client

sve tri su B00LSH1T

1 i 3 su ista stvar, svodi se na to da nece napraviti 2 ista uuid-a nikad ... e pa prc, oces, neces izmedju servera zato sto je par bajtova uuid-a deo mak adrese ili ssh kljuca servera na kom se generise ali na istom serveru, o da, moguce je da napravis 2x isti, desava se prilicno cesto (tipa bar jednom mesecno) i to ne na nekom "big data" vec na relativno malim bazama od parsto giga, ispod 1T ... a za "across databases/servers..." postoje kompozitni kljucevi koji su laksi za koriscenje i debagiranje i brzi i lepsi i nisu hype, postoje od kad i relacione baze...

2 je tek debilarijum, security through obscurity, ko ne razume nema mu svrhe objasnjavati ..

a da pricamo o negativnim stranama ... za pocetak, 64bitni bigint staje u registar, optimalno koriscenje procesora, ultra brzo skeniranje indexa, citanje, pisanje ... za 128 bita, prc nije duplo sporije nego znacajno vise nego duplo jer vise nista nije optimalno, ni vecina registra, ni l1, l2, l3 kesh, ni ram nista .. teoretski bi mogao da se koristi GPU ali je use-case suvise mali da bi se cimali pa se GPU acceleracija koristi za druge stvari (paralelizaciju FTS-a i agregatne funkcije, naravno pricam o "tamo gde GPU acceleracija postoji", sto opet nije mysql)


UUID je "solution in search of a problem" ... ne koristi ga gotovo nigde (nigde gde je vazno) nijedna velika kuca


da se vratimo na tamu "INT vs CHAR"

- bigint je brzi od bilo kog CHAR-a
- obrati paznju na default karakter set i kolacije, probleme koje mozes da imas tu kod migracije ukoliko se na to ne obrati paznja etc etc, takodje na kolicinu bitova upotrebljenih za kljuc u slucaju razlicitih karatkter setova, bez da spominjemo da razlicite kolacije mogu da uvedu duplicate entry za char pk sto tek moze da dovede do tone problema
- ako ti treba obscurity, md5, sha, sha2, sha256....
- ako ti treba reprezentacija pk-a, vec neko spomenu "prirodni" kljuc (gledaj na to kao na SEO slug na primer)
- to sto se ID vidi u URL-u je nebitno, ako ti to predstavlja problem onda ti aplikacije nije za upotrebu
[ S A J A @ 19.04.2021. 12:09 ] @
Citat:
Predrag Supurovic:
Pogrešno si to razumeo. Nije jedan privatni a jedan javni. Nego je jedan primarni ključ (PK) a jedan je prirodni ključ.

Tehnički gledano definišu se isto: radi se o vrednosti koja mora biti jedinstvena na nivou tabele.

Razlika je u tome što primarni ključ nema i ne sme da ima ama baš nikakvo značenje osim da služi da se identifikuje slog u tabeli i njega određuje sama baza u trenutku kreiranja sloga.


Ovo je sve jasno, samo u mom slučaju nema prirodnog ključa (kako ga već nazivaš). Ovaj presudo-string (ili uuid) nema nikakvo značenje, besmislen je isto kao i INT ID. Služi samo da identifikuje record.

Kad sam mislio da mi treba neki identifikator koji će biti public, nisam mislio na podatak koji će videti korisnik programa. Njemu će se prikazati spisak firmi (kojim on ima pristup) ali naravno da neće videti ID koji je u pozadini. Ali, fakat taj ID putuje u klijent browser i ako se neko potrudi, može da ga vidi.

Naravno, to nije smak sveta jer postoje prava pristupa, ne može svako da pristupi svakoj firmi ali opet, ako pustim da mi ID-ovi idu na klijent, neko može da "izbroji" koliko je novih firmi otvoreno u periodu pa tako da ima neku predstavu kako mi ide biznis... i slično.

U tom kontekstu pričam o ID-u koji je public. Zato sam mislio da umesto auto-numbera stavim neki string ili UUID. Ili, što je neko predložio, da se radi encrypt/decrypt ID broja, sad je samo pitanje šta je bolje sa stanovišta performansi. Jer, uz svaki API zahtev na server će dolaziti ID firme, a tih zahteva će biti dosta. Da li je bolje svaki put raditi decrypt ili u bazi lookup preko string-a/uuid-a.

[ Predrag Supurovic @ 19.04.2021. 12:38 ] @
Citat:
S A J A: Ovo je sve jasno, samo u mom slučaju nema prirodnog ključa (kako ga već nazivaš). Ovaj presudo-string (ili uuid) nema nikakvo značenje, besmislen je isto kao i INT ID. Služi samo da identifikuje record.

Kad sam mislio da mi treba neki identifikator koji će biti public, nisam mislio na podatak koji će videti korisnik programa. Njemu će se prikazati spisak firmi (kojim on ima pristup) ali naravno da neće videti ID koji je u pozadini. Ali, fakat taj ID putuje u klijent browser i ako se neko potrudi, može da ga vidi.

Naravno, to nije smak sveta jer postoje prava pristupa, ne može svako da pristupi svakoj firmi ali opet, ako pustim da mi ID-ovi idu na klijent, neko može da "izbroji" koliko je novih firmi otvoreno u periodu pa tako da ima neku predstavu kako mi ide biznis... i slično.

U tom kontekstu pričam o ID-u koji je public. Zato sam mislio da umesto auto-numbera stavim neki string ili UUID. Ili, što je neko predložio, da se radi encrypt/decrypt ID broja, sad je samo pitanje šta je bolje sa stanovišta performansi. Jer, uz svaki API zahtev na server će dolaziti ID firme, a tih zahteva će biti dosta. Da li je bolje svaki put raditi decrypt ili u bazi lookup preko string-a/uuid-a.


Pomenuo su da ti to treba za šifarnik komitenata i šifarnik artikala. Ta dva šifarnika imaju prirodni ključ.

Prirodni ključ je korisniku potreban. Neće on svaki putkad mu treba neki komitent ili artikal da brlja po listama, nego će tražiti da ukuca šifru koju zna i da odmah dobije traženog komitenta ili artikal. U veb šop interfejsu (ako tio pravišp) to nije toliko kritično, ali onoj drugoj strani koja barata sa tim podacima je itekako potrebno.
[ nkrgovic @ 19.04.2021. 13:26 ] @
Citat:
S A J A:
Kad sam mislio da mi treba neki identifikator koji će biti public, nisam mislio na podatak koji će videti korisnik programa. Njemu će se prikazati spisak firmi (kojim on ima pristup) ali naravno da neće videti ID koji je u pozadini. Ali, fakat taj ID putuje u klijent browser i ako se neko potrudi, može da ga vidi.

Naravno, to nije smak sveta jer postoje prava pristupa, ne može svako da pristupi svakoj firmi ali opet, ako pustim da mi ID-ovi idu na klijent, neko može da "izbroji" koliko je novih firmi otvoreno u periodu pa tako da ima neku predstavu kako mi ide biznis... i slično.

U tom kontekstu pričam o ID-u koji je public. Zato sam mislio da umesto auto-numbera stavim neki string ili UUID. Ili, što je neko predložio, da se radi encrypt/decrypt ID broja, sad je samo pitanje šta je bolje sa stanovišta performansi. Jer, uz svaki API zahtev na server će dolaziti ID firme, a tih zahteva će biti dosta. Da li je bolje svaki put raditi decrypt ili u bazi lookup preko string-a/uuid-a.

Ti znas da auto increment increment ne mora biti 1 ? :)

Takodje, ja stvarno ne vidim sto bi radio hash ili bilo sta... Ako ce neko da ti kopa API pozive kroz https, taj ce da ih iskopa. Serijalizuj json, pusti kroz https i cepaj. Ne vidim sta tacno moze da dobije neko raspakivanjem tvojih API poziva, ako imas dobro resen auth.
[ S A J A @ 19.04.2021. 13:31 ] @
Citat:
nkrgovic: Ti znas da auto increment increment ne mora biti 1 ? :)


Jel može da bude random? To bi bilo kul ;)

Citat:
nkrgovic Takodje, ja stvarno ne vidim sto bi radio hash ili bilo sta... Ako ce neko da ti kopa API pozive kroz https, taj ce da ih iskopa. Serijalizuj json, pusti kroz https i cepaj. Ne vidim sta tacno moze da dobije neko raspakivanjem tvojih API poziva, ako imas dobro resen auth.


Ne mora ništa da kopa, može da se registruje kao korisnik i otvori novu firmu i vidi ID preko konzole.
[ Shadowed @ 19.04.2021. 14:16 ] @
Citat:
nkrgovic: Ti znas da auto increment increment ne mora biti 1 ? :)

A jos ne mora ni da krece od 1 :)
[ S A J A @ 19.04.2021. 22:33 ] @
Citat:
bogdan.kecman:
da se vratimo na tamu "INT vs CHAR"
- bigint je brzi od bilo kog CHAR-a


Hteo sam ovo da izmerim pa sam napravio tabelu sa 2 kolone, INT i CHAR(12). Ovaj prvi je primarni ključ, ovaj drugi ima unique index. 7 miliona redova. U pretrazi nema nikakve razlike u brzini. U oba slučaja query traje oko 30ms. Proverio sam 20 puta i nema razlike.
[ bogdan.kecman @ 19.04.2021. 22:41 ] @
mnogo je to mali test da bi mogao da izmeris oba kljuca su ti celi u
ramu i oba su malecni

dodatno, kakav ti je to upit koji za PK/UK traje 30ms?
[ S A J A @ 19.04.2021. 22:46 ] @
Citat:
bogdan.kecman:
dodatno, kakav ti je to upit koji za PK/UK traje 30ms?


select * from test where id=12345;
[ S A J A @ 19.04.2021. 22:55 ] @
Da, kapiram, mnogo sam glup, pošto je server remote, ja sam zapravo merio internet brzinu. Kad se nakačim direktno na server, izađe mi 0.00. Jel ima neka komanda da se preciznije izmeri vreme?
[ S A J A @ 19.04.2021. 23:02 ] @
Našao sam neki profajling ali opet ne vidim neku razliku majkumu... ako ovo na 7 miliona redova radi ovako slično, to je meni dovoljno.

Code:

+----------+------------+--------------------------------------------------+
| Query_ID | Duration   | Query                                            |
+----------+------------+--------------------------------------------------+
|        2 | 0.00280050 | select * from test where char12='dd123423423423' |
|        3 | 0.00262300 | select * from test where char12='dd123423423423' |
|        4 | 0.00176075 | select * from test where char12='dd123423423423' |
|        5 | 0.00118125 | select * from test where char12='dd123423423423' |
|        6 | 0.00047325 | select * from test where char12='dd123423423423' |
|        7 | 0.00365100 | select * from test where char12='dd123423423423' |
|        8 | 0.00181625 | select * from test where char12='dd123423423423' |
|        9 | 0.00266225 | select * from test where id=123423423423         |
|       10 | 0.00049075 | select * from test where id=123423423423         |
|       11 | 0.00072550 | select * from test where id=123423423423         |
|       12 | 0.00102425 | select * from test where id=123423423423         |
|       13 | 0.00132925 | select * from test where id=123423423423         |
|       14 | 0.00280775 | select * from test where id=123423423423         |
|       15 | 0.00170150 | select * from test where id=123423423423         |
|       16 | 0.00112100 | select * from test where id=123423423423         |
+----------+------------+--------------------------------------------------+
[ Branimir Maksimovic @ 19.04.2021. 23:05 ] @
Pa ako hash tabela int je brzi za toliko sto ne mora da se hashira nego se uzima gotova vrednost dok char mora da se hasira u int. Mislim da to odradi za nemerljivo vreme tako da mu dodje na isto...
[ Shadowed @ 19.04.2021. 23:13 ] @
Ne kazem da je ovo dobra stvar ali ako si bas zapeo sa tim sto hoces, mozes ovako:
-Stavi da PK bude int ali nemoj staviti auto increment
-Kada kreiras novu firmu izvuci postojece ID-eve i kreiraj random ID od 1 do 1 000 000 koji vec nemas u listi
-Kada doguras do 10 000 firmi, promeni da ID radi auto-increment krecuci od 1 000 001. Preptostavljam da ti tada vise nece biti bitno :)


Daleko od toga da je najbrze, ali realno, koliko cesto pravis novu firmu? Kada kreiras imaces select ID-ova koji ce u najgorem slucaju imati 10 000 komada. Nalazenje random broja koji nije u toj listi je prihvatljivo brzo.
Evo, na brzinu najjednostavnija varijanta koja generise svih 10 000:
Code (csharp):

List<int> numbers = new List<int>();
Random rnd = new Random();
int newNum=1;
for (int i = 0; i < 10000; i++)
{
     while (numbers.Contains(newNum))
          newNum = rnd.Next(1000000);
     numbers.Add(newNum);
}
 

Se izvrsi za 0.05sec. Dakle, nebitno trajanje. Imas samo onaj select postojecih ID-ova. I taj select ce samo postepeno rasti. Quick and dirty ali eto, raditi ti to sto si hteo, bez da zalazimo u to da li bi trebao :)

A inace mislim da se cimas oko pogresnih stvari.
[ bogdan.kecman @ 19.04.2021. 23:35 ] @
7M i PK upit mora budu uber brzi, to je, ko sto rekoh, mala tabela ...
int poredjenje do 64bita ce uvek biti brze nego poredjenje karaktera,
posebno sto imas razliku u velicini, bigint je 64bita iliti 8 bajtova,
tesko ces ici sa char[8] obicno ces da ides sa dosta vise ... najcesci
pk su char[20] iz nekog mog iskustva kada su char[] pk to je vec sad
poredjenje 2 broja koja staju u registar vs memcmp 20 bajtova + kao sto
rekoh moguci problemi sa kolacijama i karakter setovima

inace nije ti fer poredjenje posto innodb razlicito tretira PK i taj
tvoj unique key jer je PK clustered index koji gadja direkt page gde se
nalazi data, sa druge strane taj unique index u sebi sadrzi i PK tako da
bi pravo porodjenje bilo 2 tabele sa istom datom samo u prvoj index int
u drugoj char .. no, da, na tu velicinu potupno je nebitno

procitaj https://dev.mysql.com/doc/refman/8.0/en/innodb-index-types.html

@shadowed ahhahahhah pa lakse mu je da stavi auto_increment_increment na
50 ili tako nesto :D
[ Branimir Maksimovic @ 19.04.2021. 23:42 ] @
"bogdan:"int poredjenje do 64bita ce uvek biti brze nego poredjenje karaktera, "

To ako je indeks binarno stablo ako je hash tabela onda je upit O(1) tako da nema veze...

edit: pardon ne binarno stablo, nego btree posto to baze koriste.
[ bogdan.kecman @ 20.04.2021. 00:34 ] @
hash je uzasno specifican slucaj, ne podrzava range query, ne podrzava
"delove" composity key-a, ne postoji mogucnost pretpostavke velicine
rezultata pa je i cost base optimizer nemoguc, ne mozes da imas
multivalued index kao hash etc etc ...

jos ako uzmemo da je u pitanju mysql HASH index je podrzan samo u
in-memory SE  (memory i ndbcluster) koje sigurno nece koristiti, sto ce
reci innodb i myisam ne podrzavaju hash tako da prica o toma kako bi
hash radio kada bi bio podrzan prilicno nebitna u ovom slucaju ...
fraktalni indexi imaju jos bolje ponasanje u mnogim slucajevima al ne
rade na mysql-u (tokudb sa druge strane...)
[ nkrgovic @ 20.04.2021. 08:10 ] @
Po meni je i dalje jako glupo komplikovati.... Stavis int (big int) za primarni kljuc, auto increment. Ostavis i auto increment increment na 1. Nije problem sad, bice problem kad budes nesto dodao za 4 godine, pa ide join tri tabele po PK-u....

U API pozivu, umesto po ID-u firme trazis po maticnom broju ili PIB-u. Oba polja imas u tabeli gde drzis podatke o firmi, oba su isto integer, po oba ces, skoro sigurno, imati index. I dalje ne kapiram taj security trough obscurity, ali eto, po meni najprirodnije resenje, ubaci u API nesto sto nije ID iz baze i resio si.
[ bogdan.kecman @ 21.04.2021. 05:07 ] @
btw super txt koji je vlad napisao, treba procitati: https://vladmihalcea.com/clustered-index/
[ mjanjic @ 21.04.2021. 11:39 ] @
Neko pomenu Natural Key, ako je PIB jedan od podataka, a u pitanju je int i mora biti jedinstven za svaku firmu, onda on može da se koristi za sve na front-u, tj. PK i ako postoji, ne mora da se prosleđuje eksterno, već samo interno da se koristi ako uopšte za tim ima potrebe.
[ S A J A @ 21.04.2021. 12:05 ] @
Ako postoji natural key, to nije nikakav problem, samo što u mom slučaju on ne postoji. Ovo nisu firme u smislu pravih registrovanih firmi, niti je u pitanju striktno Srbija, ti možeš da se uloguješ pa da otvoriš "firmu" koja recimo još nije registrovana, nekakav tim, startup, klub, versku zajednicu, politički pokret, bandu, štagod... Šta je u svemu tome natural key? Nema ga. Meni treba običan ID za identifikaciju ali pošto je sistem client-server, ne bih hteo da autonumber ide na clijent. Zato sam i mislio da to bude neki besmislen string. Koliko sam primetio, na 7 miliona slogova nema nikakvog pada u performansama tako da je to meni dovoljno. Plus, neće upit po tome biti toliko čest, jednom kad nađem ko je u pitanju, stavim ga u memory keš i svaki sledeći zahtev neće ni dolaziti do baze.
[ Predrag Supurovic @ 21.04.2021. 14:21 ] @
Citat:
S A J A: Ako postoji natural key, to nije nikakav problem, samo što u mom slučaju on ne postoji. Ovo nisu firme u smislu pravih registrovanih firmi, niti je u pitanju striktno Srbija, ti možeš da se uloguješ pa da otvoriš "firmu" koja recimo još nije registrovana, nekakav tim, startup, klub, versku zajednicu, politički pokret, bandu, štagod... Šta je u svemu tome natural key? Nema ga. Meni treba običan ID za identifikaciju ali pošto je sistem client-server, ne bih hteo da autonumber ide na clijent. Zato sam i mislio da to bude neki besmislen string. Koliko sam primetio, na 7 miliona slogova nema nikakvog pada u performansama tako da je to meni dovoljno. Plus, neće upit po tome biti toliko čest, jednom kad nađem ko je u pitanju, stavim ga u memory keš i svaki sledeći zahtev neće ni dolaziti do baze.


Ja bih ipak rekao da ti tu samo ne vidiš prirodni ključ.

Recimo ovako: prirodni ključ uvek postoji. To je ključ koji jednoznačno određuje entitet koji je opisan slogom. Primarni ključ je ključ koji određuje sam slog.

Interesantno mi je da ti ne vidiš problem koji sam sebi praviš tako što insistiraš da ne postoji prirodni ključ u toj tvojoj tabeli, ali ti ne odgovarakako se generiše primarni ključ pa bi to da prilagođavaš.

Odvoj ih. Pusti primarni ključ da radi svoj posao a uvedi prirodni ključ koji ćeš da oblikuješ kako god da ti odgovara i rešio si problem. Ako ti se i desi da posle nekog vremena ustanoviš da način kako kreiraš prirodni ključ baš i nije najbolji, uvek možeš to da promeniš a da to uopšte ne dotiče arhitekturu cele baze jer se ona oslanja na primarni ključ.

Čak i ako ostaneš pri tom da ti odgovara da sadržaj primarnog ključa može da ima ulogu prirodnog ključa onda napravi da tako i bude - koristi sadržaj primarnog ključa kao prirodni ključ, ali to su i dalje dva ključa. Prirodni ključ ne mora da bude stvarno polje u tabeli, to može da bude i izračunato (calculated) polje.
[ S A J A @ 21.04.2021. 14:50 ] @
Ok, znači predlažeš da imam klasičan INT autonumber PK koji bi bio u tabli i ničemu ne bi služio, i da napravim poseban prirodni ključ koji je recimo CHAR(12), npr. "14dda8872b0e" koji bi se koristio u komunikaciji sa klijent aplikacijom? Pošto bi zahtevi od strane klijent aplikacije dolazili samo sa tim prirodnim ključem i pretraga bi radila po tome, šta konkretno dobijam time što imam dve kolone za identifikaciju a realno mi treba samo jedna?
[ madamov @ 21.04.2021. 16:09 ] @
Ako ćeš ikada da sinhronizuješ baze, onda uzmi 128-bitni integer, ne znam za MySQL, u mom alatu postoji tip UUID, uštedećeš sebi mnogo muke kada jednog dana bude trebalo da nešto sinhronizuješ.
[ Predrag Supurovic @ 21.04.2021. 21:09 ] @
Citat:
S A J A:
Ok, znači predlažeš da imam klasičan INT autonumber PK koji bi bio u tabli i ničemu ne bi služio, i da napravim poseban prirodni ključ koji je recimo CHAR(12), npr. "14dda8872b0e" koji bi se koristio u komunikaciji sa klijent aplikacijom? Pošto bi zahtevi od strane klijent aplikacije dolazili samo sa tim prirodnim ključem i pretraga bi radila po tome, šta konkretno dobijam time što imam dve kolone za identifikaciju a realno mi treba samo jedna?


Pa ne bi imao dve kolone za identifikaciju entiteta nego samo jednu: prirodni ključ.
Primarni ključ ne bi služio za identifikaciju entiteta nego za povezivanje tabela.

Kada tražiš entitet koristiš prirodni ključ. Kada povezuješ tabele onda koristiš primarni ključ.