Wolny Npgsql

0

Cześć

W miarę nauki C# chciałem przepisać kod w PHP który wygląda następująco:

$dbh = new PDO(*****);
$sql_add = 'INSERT INTO historia (symbol,czas,ilosc,cena,kod1,kod2,kod3) VALUES(?,?,?,?,?,?,?)';
$stmt_add = $dbh->prepare($sql_add);

function InsertData($xml_file, &$i) {
    global $stmt_add;
    
    $xml = new SimpleXMLElement(file_get_contents($xml_file));

    foreach ($xml->Zlecania as $res) {
        $symbol= $res->Symbol;
        
        foreach ($res->Zlecenie as $zlecenie) {
           list($d, $t) = preg_split("/ /", $trade->Czas);
           list($mon, $day, $year) = preg_split("/\//", $d);
           $czas= "$year-$mon-$day $t";
           
            $i++;
            $stmt_add->execute(array($symbol, $czas, $zlecenie->Ilosc, $zlecenie->Cena, $zlecenie->Kod1, $zlecenie->Kod2, $zlecenie->Kod3));
        }
    }
    $xml = null;
}
 

Czas na przeanalizowanie pliku XML o wielkość 30MB zajmuje na moim laptopku(starym) okolo 3,5sekundy a z dodawaniem do bazy oscyluje pomiędzy 65-70 sekund
Ilość zapytań wynosi 71k.

Chciałem przepisać ten kod na C#. Za pomocą XMLDocument załadowanie i przeanalizowanie danych zajmuje około 1,8 sekundy(ten sam plik XML). Problem pojawił się przy insertach. Mój kod nie potrafi 'zejść' poniżej 80 sekund dla tych 71k zapytań. Kod wygląda tak:

 

namespace PgFun
{
 public partial class Form1 : Form
    {
        public XmlDocument xmldoc = new XmlDocument();
        public NpgsqlConnection conn = new NpgsqlConnection(****);
        public Form1()
        {
            conn.Open();

            InitializeComponent();


        }
[......]

 private void ToolStripButtonLoad_Click(object sender, EventArgs e)
        {
            DateTime startTime = DateTime.Now;
            NpgsqlCommand command = new NpgsqlCommand("INSERT INTO historia(symbol,czas,ilosc,cena,kod1,kod2,kod3) VALUES(:symbol,:czas,:ilosc,:cena,:kod1,:kod2,:kod3)", conn);

            command.Parameters.Add(new NpgsqlParameter("symbol", NpgsqlDbType.Text));
            command.Parameters.Add(new NpgsqlParameter("czas", NpgsqlDbType.Timestamp));
            command.Parameters.Add(new NpgsqlParameter("ilosc", NpgsqlDbType.Integer));
            command.Parameters.Add(new NpgsqlParameter("cena", NpgsqlDbType.Double));
            command.Parameters.Add(new NpgsqlParameter("kod1", NpgsqlDbType.Integer));
            command.Parameters.Add(new NpgsqlParameter("kod2", NpgsqlDbType.Integer));
            command.Parameters.Add(new NpgsqlParameter("kod3", NpgsqlDbType.Integer));
            command.Prepare();
         
         
            int cnt = 0;

            string myXMLfile = @"plik.xml";

            xmldoc.Load(myXMLfile);

            foreach (XmlNode node in xmldoc.DocumentElement.ChildNodes)
            {
                command.Parameters["symbol"].Value = node["Symbol"].InnerText;
                foreach (XmlNode zlec in node["Zlecenia"])
                {
                    command.Parameters["czas"].Value = DateTime.Parse(zlec["Czas"].InnerText, CultureInfo.InvariantCulture, DateTimeStyles.None);
                    command.Parameters["ilosc"].Value = int.Parse(zlec["Ilosc"].InnerText);
                    command.Parameters["cena"].Value = double.Parse(zlec["Cena"].InnerText, CultureInfo.InvariantCulture);
                    command.Parameters["kod1"].Value = int.Parse(zlec["kod1"].InnerText);
                    command.Parameters["kod2"].Value = int.Parse(zlec["kod2"].InnerText);
                    command.Parameters["kod3"].Value = int.Parse(zlec["kod3"].InnerText);

                    command.ExecuteNonQuery();
                    cnt++;
                }
            }

            DateTime stopTime = DateTime.Now;
            TimeSpan elapsed = stopTime - startTime;
            label1.Text = elapsed.TotalSeconds.ToString() + " ---- " + cnt;

Co tutaj mogę poprawić ? Jaka jest tego przyczyna ?

Kod PHP wykonuje PHP5.4.5
Kod C# pisany jest z NET4.0

dzięki
dawid

0

Mierzyłeś czas na debug czy release?

0

Użyj na początku transakcji - powinno sporo przyśpieszyć operacje.

0
ozi88 napisał(a):

Użyj na początku transakcji - powinno sporo przyśpieszyć operacje.

o tak :-) to znacznie zwiększyło prędkość. 58-60 sekund. Dodałem jeszcze Prepare() i czas trzyma się 49 sekund ! :-D

  private void ToolStripButtonLoad_Click(object sender, EventArgs e)
        {
            string myXMLfile = @"plik.xml";
            DateTime startTime = DateTime.Now;
            NpgsqlTransaction pgTrans = (NpgsqlTransaction)conn.BeginTransaction();
            NpgsqlCommand command = new NpgsqlCommand("INSERT INTO historia(symbol,czas,ilosc,cena,kod1,kod2,kod3) VALUES(:symbol,:czas,:ilosc,:cena,:kod1,:kod2,:kod3)", conn,pgTrans);
 
            command.Parameters.Add(new NpgsqlParameter("symbol", NpgsqlDbType.Text));
            command.Parameters.Add(new NpgsqlParameter("czas", NpgsqlDbType.Timestamp));
            command.Parameters.Add(new NpgsqlParameter("ilosc", NpgsqlDbType.Integer));
            command.Parameters.Add(new NpgsqlParameter("cena", NpgsqlDbType.Double));
            command.Parameters.Add(new NpgsqlParameter("kod1", NpgsqlDbType.Integer));
            command.Parameters.Add(new NpgsqlParameter("kod2", NpgsqlDbType.Integer));
            command.Parameters.Add(new NpgsqlParameter("kod3", NpgsqlDbType.Integer));
         command.Prepare();
 
             int cnt = 0;
            xmldoc.Load(myXMLfile);
 
            foreach (XmlNode node in xmldoc.DocumentElement.ChildNodes)
            {
                command.Parameters["symbol"].Value = node["Symbol"].InnerText;
                foreach (XmlNode zlec in node["Zlecenia"])
                {
                    command.Parameters["czas"].Value = DateTime.Parse(zlec["Czas"].InnerText, CultureInfo.InvariantCulture, DateTimeStyles.None);
                    command.Parameters["ilosc"].Value = int.Parse(zlec["Ilosc"].InnerText);
                    command.Parameters["cena"].Value = double.Parse(zlec["Cena"].InnerText, CultureInfo.InvariantCulture);
                    command.Parameters["kod1"].Value = int.Parse(zlec["kod1"].InnerText);
                    command.Parameters["kod2"].Value = int.Parse(zlec["kod2"].InnerText);
                    command.Parameters["kod3"].Value = int.Parse(zlec["kod3"].InnerText);
 
                    command.ExecuteNonQuery();
                    cnt++;
                }
            }

            pgTrans.Commit();
            DateTime stopTime = DateTime.Now;
            TimeSpan elapsed = stopTime - startTime;
            label1.Text = elapsed.TotalSeconds.ToString() + " ---- " + cnt;

Dzięki ozi88

1

Możesz zainteresować się jeszcze insertem batchowym (np. z pliku) jeżeli chcesz opisu jak to zrobić to tutaj znajdziesz go: http://patryknet.blogspot.com/2012/09/dodawanie-duzej-ilosci-rekordow-do-bazy.html - jako 3 metoda

0
ozi88 napisał(a):

Możesz zainteresować się jeszcze insertem batchowym (np. z pliku) jeżeli chcesz opisu jak to zrobić to tutaj znajdziesz go: http://patryknet.blogspot.com/2012/09/dodawanie-duzej-ilosci-rekordow-do-bazy.html - jako 3 metoda

Coś pięknego. Milion insertów w minute. Super. Wielkie dzięki jeszcze raz

0

kontynuacja: Time Series Database

1 użytkowników online, w tym zalogowanych: 0, gości: 1