2010-01-12 11 views
9

Ho un progetto con 2 applicazioni (libri e lettore).Tavolo Django con milioni di righe

applicazione

Libri ha un tavolo con 4 Milioni di righe con questi campi:

book_title = models.CharField(max_length=40) 
book_description = models.CharField(max_length=400) 

Per evitare di interrogare il database con 4 Milioni di righe, sto pensando di dividerlo per argomento (20 modelli con 20 . tabelle con 200.000 righe (book_horror, book_drammatic, ecc)

In "lettore" di applicazione, sto pensando di inserire questi campi:

reader_name = models.CharField(max_length=20, blank=True) 
book_subject = models.IntegerField() 
book_id = models.IntegerField() 

Così, invece di ESTERA nKey, sto pensando di usare un intero "book_subject" (che consente di accedere alla tabella appropriata) e "book_id" (che consente di accedere al libro nella tabella specificata in "book_subject").

È una buona soluzione per evitare di interrogare una tabella con 4 milioni di righe?

Esiste una soluzione alternativa?

Grazie^__^

+8

4 milioni non sono molti, si ha un caso di ottimizzazione prematura. – Tobu

+0

La tabella viene interrogato da Ajax utilizzando un campo di completamento automatico con questo query nel views.py: books.objects.filter (book_title__istartswith = request.GET [ 'q']) [: 100] – xRobot

+0

Se si sta eseguendo la query di un tabella su un campo di testo e le prestazioni sono il problema, si può scegliere di implementare la ricerca full-text. Tuttavia, le dimensioni del campo interrogato sono solo 40 caratteri, e non sono sicuro che rappresenti un grosso problema per il db. – shanyu

risposta

12

Come molti hanno già detto, è un po 'prematuro dividere il tavolo in tabelle più piccole (partizionamento orizzontale o persino sharding). I database sono fatti per gestire tabelle di queste dimensioni, quindi il tuo problema di prestazioni è probabilmente da qualche altra parte.

Gli indici sono il primo passo, sembra che tu l'abbia fatto. 4 milioni di file dovrebbero essere ok per gestire il db con un indice.

In secondo luogo, controllare il numero di query in esecuzione. Puoi farlo con qualcosa come la barra degli strumenti di debug di Django, e sarai spesso sorpreso di quante query inutili sono state fatte.

Il caching è il passaggio successivo, utilizzare memcached per pagine o parti di pagine che sono invariate per la maggior parte degli utenti. Questo è dove vedrai il tuo più grande incremento di prestazioni per il piccolo sforzo richiesto.

Se davvero, davvero bisogno di dividere i tavoli, l'ultima versione di django (1.2 alpha) può gestire lo sharding (es. Multi-db), e dovresti essere in grado di scrivere una soluzione di partizionamento orizzontale (offerte postgres un modo in-db per farlo). Per favore non usare il genere per dividere i tavoli! scegli qualcosa che non vorresti mai, mai cambiare e che saprai sempre quando fai una query. Come autore e dividi per prima lettera del cognome o qualcosa del genere. Questo è un grande sforzo e ha un certo numero di inconvenienti per un database che non è particolarmente grande --- questo è il motivo per cui la maggior parte delle persone qui sta sconsigliarlo!

[modifica]

ho lasciato fuori denormalizzazione! Inserisci i conteggi comuni, le somme ecc. Nella tabella dell'autore, ad esempio, per evitare join su query comuni. Il rovescio della medaglia è che devi mantenerlo da solo (fino a quando Django aggiunge un campo denormalizzato). Guarderei questo durante lo sviluppo per casi chiari e semplici o dopo che la cache ha fallito - ma well prima di sharding o partizionamento orizzontale.

+0

Ok se Ho diviso il tavolo, io vi dividerlo dalla prima lettera ... anzi è più ragionevole :) La tabella viene interrogato da Ajax utilizzando un campo di completamento automatico con questo query nel views.py: libri .objects.filter (book_title__istartswith = request.GET ['q']) [: 100] Quindi mi consigliate index + memcached? Grazie – xRobot

+0

Crea un indice sulle prime tre lettere del titolo (o qualunque sia il primo numero che inizi a interrogare il database) e verrà eseguito abbastanza velocemente. – naivists

10

ForeignKey viene implementato come IntegerField nel database, in modo da risparmiare poco o niente a costo di paralizzare il vostro modello.

Modifica: E per l'amor del cielo, tenerlo in una tabella e utilizzare gli indici in modo appropriato.

+0

Sto usando l'indice ma il tavolo ha 4 milioni di file ed è spesso richiesto. Quindi non so se l'indice è sufficiente: - \ – xRobot

+0

Se non lo è, il database ha bisogno di più memoria. –

+2

4 milioni di righe non sono altro che starnutire, ma i database sono costruiti per questo tipo di cose, specialmente se stai indicizzando.Mi preoccuperei solo se ti stai alzando almeno a cento milioni di file. – LeafStorm

0

Non ho familiarità con Django, ma ho una conoscenza generale di DB.

Quando si dispone di database di grandi dimensioni, è normale per index your database. In questo modo, il recupero dei dati dovrebbe essere piuttosto veloce.

Quando si associa un libro a un lettore, è necessario creare un'altra tabella che colleghi il lettore ai libri.

Non è una cattiva idea dividere i libri in soggetti. Ma non sono sicuro di cosa intendi con 20 applicazioni.

+0

20 applicazioni significa 20 tabelle :) \t Sto usando già l'indice ma la tabella ha 4 milioni di righe ed è spesso interrogato. Quindi non so se l'indice è sufficiente: - \ – xRobot

+1

Gods no! Non dividerlo in 20 tavoli! Crea un diagramma EAR delle tue tabelle e vedrai quale tabella aggiuntiva ti servirà per gestirle. Per esempio. tavoli extra per relazionarsi a libri, categorie a libri e così via. – Steven

0

Si verificano problemi di prestazioni? In tal caso, potrebbe essere necessario add a few indexes.

Un modo per avere un'idea di dove un indice sarebbe utile è guardare il log delle query del server db (instructions here se si è su MySQL).

Se non si verificano problemi di prestazioni, è sufficiente seguirlo. I database sono fatti per gestire milioni di record e django è abbastanza bravo a generare query ragionevoli.

+0

Sì, è un problema di prestazioni. Sto usando l'indice ma la tabella ha 4 milioni di righe ed è spesso richiesta. Quindi non so se l'indice è sufficiente: - \ – xRobot

+0

Un indice più grande (più colonne) è probabilmente la strada da percorrere, forse oltre a memcached come menzioni @jcm. Spesso gli indici a colonna singola non aiutano perché non vengono utilizzati dalle query. – Seth

0

Un approccio comune a questo tipo di problema è Sharding. Sfortunatamente dipende principalmente dall'ORM (Hibernate lo fa meravigliosamente) e Django non lo supporta. Tuttavia, non sono sicuro che 4 milioni di file siano davvero così male. Le tue domande dovrebbero essere ancora interamente gestibili.

Forse dovresti cercare nella cache con qualcosa come memcached. Django supports this abbastanza bene.

1

Non hai menzionato quale database stai usando. Alcuni database, come MySQL e PostgreSQL, hanno impostazioni estremamente conservative out-of-the-box, che sono fondamentalmente inutilizzabili per qualsiasi cosa, tranne piccoli database su server minuscoli.

Se ci dici quale database stai usando, e su quale hardware è in esecuzione, e se tale hardware è condiviso con altre applicazioni (è anche in grado di servire l'applicazione web, per esempio) allora potremmo essere in grado di dare qualche consiglio specifico sull'ottimizzazione.

Ad esempio, con MySQL, sarà probabilmente necessario regolare le impostazioni di InnoDB; per PostgreSQL, dovrai modificare shared_buffers e una serie di altre impostazioni.

Problemi correlati