Καλώς ορίσατε στο dotNETZone.gr - Σύνδεση | Εγγραφή | Βοήθεια
σε

 

Αρχική σελίδα Ιστολόγια Συζητήσεις Εκθέσεις Φωτογραφιών Αρχειοθήκες

Entity Framework Massive Update

Îåêßíçóå áðü ôï ìÝëïò koslyr. Τελευταία δημοσίευση από το μέλος Markos στις 24-07-2012, 20:16. Υπάρχουν 3 απαντήσεις.
Ταξινόμηση Δημοσιεύσεων: Προηγούμενο Επόμενο
  •  23-07-2012, 01:49 70958

    Entity Framework Massive Update

    Θέλω σε ένα table στον SQL-Server να κάνω update τρια fields σε, σύνολο περίπου 5.000.000 εγγραφών .
    Για την επικοινωνία με την βάση χρησιμοποιώ το Entity Framework και για το update μάλλον θα κάνω χρήση της LINQ (http://www.ezineasp.net/post/LINQ-to-Entities-Update-Operation-using-C-Sharp.aspx).
    Όμως επειδή το σύνολο των εγγραφών που θελω να ενημερώσω είναι αρκετά μεγάλο σκεφτόμουνα μήπως τελικά είναι προτιμότερο από άποψη performance να επιλέξω τον παλιό παραδοσιακό ADO.Net με Dataset & DataAdapter ή καλύτερα να παραμείνω στο EF για ομοιογένεια.
  •  23-07-2012, 13:55 70963 σε απάντηση της 70958

    Απ: Entity Framework Massive Update

    Είναι εντελώς λάθος να χρησιμοποιήσεις ένα ORM για batch updates γενικά, πόσο μάλλον όταν μιλάς για πολλές εγγραφές. Τα ORM υπάρχουν για να μπορείς να χρησιμοποιήσεις αντικείμενα με συγκεκριμένη συμπεριφορά στην εφαρμογή σου χωρίς να ασχολείσαι πως θα τα φορτώσεις από τη βάση. Εσύ όμως θέλεις απλά να πειράξεις πεδία στη βάση - δεν υπάρχει κανένα είδος συμπεριφοράς αντικειμένου εδώ. Για την ακρίβεια, δεν υπάρχουν καν αντικείμενα, μόνο πεδία κάποιου πίνακα.

    Είναι επίσης λάθος να χρησιμοποιήσεις ADO.NET ή οποιαδήποτε άλλη client τεχνολογία. Για ποιό λόγο θα πρέπει να μεταφέρεις 5000000 εγγραφές στον client όταν θέλεις μόνο να κάνεις update στον server? Σκέψου μόνο πόσο κοστίζει η μεταφορά τόσων εγγραφών από το server στον client και μετά πάλι πίσω. Το αποτέλεσμα θα είναι να κρατήσει η διαδικασία πολύ περισσότερο απ' ότι περίμενες (μιλάμε για τάξεις μεγέθους), με πολύ μεγάλη πιθανότητα (~100%) να διακοπεί λόγω concurrency violations αν κάποιος άλλος κάνει updates στον πίνακα.

    Η μόνη σωστή λύση εδώ είναι να χρησιμοποιήσεις SQL κώδικα για να κάνεις το batch update απευθείας στη βάση. Ακόμα και έτσι, θα πρέπει να προσέξεις πως θα κάνεις ένα τόσο μεγάλο update, καθώς τα κλειδώματα που θα γίνουν στη βάση θα κρατήσουν για πολλή ώρα με αποτέλεσμα να δημιουργήσεις πρόβλημα σε οποιονδήποτε άλλο χρησιμοποιεί τη βάση σου. Επιπλέον, μία τέτοια μαζική αλλαγή θα δημιουργήσει πολλές εγγραφές στο transaction log.

    Τέλος, θα πρέπει να σκεφτείς ΓΙΑΤΙ χρειάζονται τόσο πολλά updates? Μία τέτοια απαίτηση συνήθως κρύβει κάποιο σχεδιαστικό λάθος. Τί είναι τα πεδία που θέλεις να αλλάξεις? Μήπως πρόκειται για λίγες τιμές οι οποίες θα έπρεπε να βρίσκονται σε ένα άλλο πίνακα αντί να επαναλαμβάνονται σε κάθε γραμμή? 



    Παναγιώτης Καναβός, Freelancer
    Twitter: http://www.twitter.com/pkanavos
  •  23-07-2012, 21:57 70965 σε απάντηση της 70963

    Απ: Entity Framework Massive Update

    Παναγιώτης Καναβός:
    Είναι εντελώς λάθος να χρησιμοποιήσεις ένα ORM για batch updates γενικά, πόσο μάλλον όταν μιλάς για πολλές εγγραφές. Τα ORM υπάρχουν για να μπορείς να χρησιμοποιήσεις αντικείμενα με συγκεκριμένη συμπεριφορά στην εφαρμογή σου χωρίς να ασχολείσαι πως θα τα φορτώσεις από τη βάση. Εσύ όμως θέλεις απλά να πειράξεις πεδία στη βάση - δεν υπάρχει κανένα είδος συμπεριφοράς αντικειμένου εδώ. Για την ακρίβεια, δεν υπάρχουν καν αντικείμενα, μόνο πεδία κάποιου πίνακα.
    Είναι επίσης λάθος να χρησιμοποιήσεις ADO.NET ή οποιαδήποτε άλλη client τεχνολογία. Για ποιό λόγο θα πρέπει να μεταφέρεις 5000000 εγγραφές στον client όταν θέλεις μόνο να κάνεις update στον server? Σκέψου μόνο πόσο κοστίζει η μεταφορά τόσων εγγραφών από το server στον client και μετά πάλι πίσω. Το αποτέλεσμα θα είναι να κρατήσει η διαδικασία πολύ περισσότερο απ' ότι περίμενες (μιλάμε για τάξεις μεγέθους), με πολύ μεγάλη πιθανότητα (~100%) να διακοπεί λόγω concurrency violations αν κάποιος άλλος κάνει updates στον πίνακα.
    Η μόνη σωστή λύση εδώ είναι να χρησιμοποιήσεις SQL κώδικα για να κάνεις το batch update απευθείας στη βάση. Ακόμα και έτσι, θα πρέπει να προσέξεις πως θα κάνεις ένα τόσο μεγάλο update, καθώς τα κλειδώματα που θα γίνουν στη βάση θα κρατήσουν για πολλή ώρα με αποτέλεσμα να δημιουργήσεις πρόβλημα σε οποιονδήποτε άλλο χρησιμοποιεί τη βάση σου. Επιπλέον, μία τέτοια μαζική αλλαγή θα δημιουργήσει πολλές εγγραφές στο transaction log.
    Τέλος, θα πρέπει να σκεφτείς ΓΙΑΤΙ χρειάζονται τόσο πολλά updates? Μία τέτοια απαίτηση συνήθως κρύβει κάποιο σχεδιαστικό λάθος. Τί είναι τα πεδία που θέλεις να αλλάξεις? Μήπως πρόκειται για λίγες τιμές οι οποίες θα έπρεπε να βρίσκονται σε ένα άλλο πίνακα αντί να επαναλαμβάνονται σε κάθε γραμμή? 

    Η συγκεκριμένη εργασία που αφορά την ενημέρωση του πεδίου αυτού σε αυτόν τον Πίνακα με τις 5.000.000 εγγραφές, γίνεται μια φορά τον χρόνο οπότε δεν προκειται για μια καθημερινή ή εβδομαδιαία εργασία, παρόλα αυτά θα με ενδιέφερε να υλοποιηθεί με τον βελτιστο τρόπο ώστε να ολοκληρώνεται στο ταχύτερο χρονικό διάστημα.
    Όπως ανέφερες μάλλον με το ORM δεν θα μπορέσω να έχω το επιθυμητό αποτέλεσμα, αλλά για λογους ομοιογένειας κώδικα στην εφαρμογή μου που αφορά όλα το Data Access Layer  ήμουνα σε αναζήτηση μήπως βρω κάτι για την συγκεκριμένη υλοποίηση, ώστε η όλη επικοινωνία με την βάση να γίνεται μέσα από το Entity-Framework.
    Επιπλέον για την χρήση του DataSet μάλλον θα ήταν χειρότερα να μεταφερω τοπικά στην μνήμη του client 5.000.000 εγγραφές. Το μόνο καλό στην περίπτωση αυτήν θα ήταν το μαζικό update μέσω του DataAdapter.
    Για την υλοποίηση του Update μεσω ενός Store Procedure δεν με πολυ-βολευει, καθώς η ενημέρωση του πεδίου αυτού απαιτεί έναν σχετικά σύνθετο αλγόριθμο που μπορώ καλύτερα να τον διαχειρτιστώ σε C# παρά σε T-SQL.

    Αρχικά σκεφτόμουνα μια αρχική υλοποίηση σαν την παρακάτω για το μαζικό update:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
     
    public void Execute()
            {
                SqlConnection readerConnection = new  
                SqlConnection(Properties.Settings.Default.ConnectionString);
                readerConnection.Open();
    
                SqlCommand cmd = new SqlCommand("SELECT ......", readerConnection);
                SqlDataReader reader = cmd.ExecuteReader();
    
                SqlConnection writerConnection = new SqlConnection(Properties.Settings.Default.ConnectionString);
                writerConnection.Open();
    
                SqlCommand writerCommand = new SqlCommand("", writerConnection);
    
                while (reader.Read())
                {
                    //Do the process
                    writerCommand.CommandText = "UPDATE ......";
                    writerCommand.ExecuteNonQuery();
                }


     
  •  24-07-2012, 20:16 70974 σε απάντηση της 70965

    Απ: Entity Framework Massive Update

    Θα συμφωνήσω με τον Παναγιώτη, αλλά με τη σειρά μου θα ήθελα να ρωτήσω τι μπορεί να είναι τόσο περίπλοκο που δε μπορεί να γίνει με T-SQL. Επίσης, μήπως πρέπει να τροποποιήσεις λίγο το business logic, έτσι ώστε να μην χρειάζεται να γίνονται τέτοιου είδους updates κάθε χρόνο; Άντε να γίνει μια φορά με το στήσιμο της εφαρμογής, αλλά κι εμένα δε μου πάει το μυαλό τι είδους update μπορεί να είναι αυτό ώστε να τρέχει μια φορά το χρόνο. Και οι εγγραφές είναι 5.000.000 τώρα. Του χρόνου μπορεί να είναι 10 ή 15-μύρια, και πάει λέγοντας...

    Ακόμα κι ένας άνθρωπος μπορεί ν' αλλάξει τον κόσμο. Μη θέλεις να κυβερνήσεις. Απλά δείξε το μονοπάτι κι ο κόσμος θ' ακολουθήσει!!
Προβολή Τροφοδοσίας RSS με μορφή XML
Με χρήση του Community Server (Commercial Edition), από την Telligent Systems