2013-10-24 12 views
1

Я хотел сделать обновление по потенциально миллионным записям. Я люблю Linq, и я написал это ниже, чтобы попытаться выполнить это. Я действительно надеюсь, что написал это ужасно неправильно. Потрачено время и часы. Я написал его в T-sql, и он заработал минут. Есть ли лучший способ сделать это с помощью linq?Экстремальная медленность с Linq при массовом обновлении

private static void UpdateZipCodes() 
      { 
       Console.WriteLine("Update Zip Codes Started"); 
       DataDataContext _db = new DataDataContext(); 


       var newBadZips = (from n in _db.NewCars 
            where n.loczip == null || n.loczip == "" 
            select n).ToList(); 
       foreach (var bad in newBadZips) 
       { 
        string lZip = _db.Dealers.Where(x => x.DealerID == bad.DealerID).Select(x => x.Zipcode).SingleOrDefault(); 

        bad.loczip = lZip; 
        _db.SubmitChanges(); 


       } 
       Console.WriteLine("Update Zip Codes Finshed"); 
      } 

T-Sql версия

UPDATE n 

SET n.loczip = d.Zipcode 

FROM   NewCars AS n INNER JOIN 
         Dealers AS d ON n.DealerID = d.DealerID 
         where n.loczip is null or n.loczip = '' 

Я понимаю, что очевидно из этого LINQ делает больше. Я хочу знать, как мой linq-запрос может быть улучшен?

Я не пытаюсь сравнивать их в том смысле, что знаю, что T-sql - это правильный способ выполнить это. Это в основном для меня становится лучше при использовании linq. Я уверен, что когда-нибудь захочу сделать что-то подобное в меньшем масштабе и хочу сделать это правильно в linq.

+2

Что вы подразумеваете под «использованием удалений»? –

+0

@zespri Спасибо, что поймали этот плохой титул. – jackncoke

+1

Я мог ошибаться, но возможно потому, что вы делаете 3 разных действия в коде против версии T-SQL. Вы запрашиваете базу данных и сохраняете список, затем выполняете итерацию по списку, а затем обновляете базу данных из этого списка. С миллионами записей это займет довольно много времени. – MyCodeSucks

ответ

6

Вы запрашиваете свою базу данных для каждого элемента в цикле. Плохо. Это почти всегда неправильно и будет практически всегда очень медленным.

Как и в вашем коде T-SQL, используйте команду Join в вашем LINQ-коде, чтобы получить всю необходимую информацию в одном запросе.

Далее, не обновляйте базу данных после каждой записи; вместо этого обновляйте их партиями, чтобы уменьшить сетевой трафик. Вы не сможете сделать миллион всех одновременно, но вы можете отправить партию каждые 100 или 1000 или любые строки (поиграйте с разными значениями размера партии, чтобы увидеть, что лучше всего работает).

Кроме того, не звоните ToList на стол с миллионом записей. Просто повторите запрос, чтобы поставщик запросов мог передавать данные.

var newBadZips = (from car in _db.NewCars 
         where car.loczip == null || car.loczip == "" 
         join dealer in _db.Dealers 
         on car.DealerID equals dealer.DealerID 
         into dealers 
         select new{ 
          car, 
          zip = dealers.Select(d => d.Zipcode) 
          .SingleOrDefault(), 
         }); 

int count = 0; 
int batchSize = 1000; 
foreach(var row in newBadZips) 
{ 
    row.car.loczip = row.zip; 
    if(++count % batchSize == 0) 
     _db.SubmitChanges(); 
} 
+0

Обратите внимание, что даже в этой ситуации код LINQ по-прежнему будет намного медленнее, чем просто выпустить инструкцию обновления напрямую. – NotMe

+1

@ChrisLively Вероятно, да. Но не так много, и, возможно, на приемлемом уровне. – Servy

+0

Я не пытаюсь сравнивать их в том смысле, что знаю, что T-sql - это правильный способ выполнить это. Это в основном для меня становится лучше при использовании linq. Я уверен, что когда-нибудь захочу сделать что-то подобное в меньшем масштабе и хочу сделать это правильно в linq. – jackncoke

4

Абсолютно лучший способ увеличить скорость LINQ в этой ситуации - просто не использовать LINQ. Либо запустите свой запрос на обновление T-SQL напрямую, либо бросьте его в proc, и вызовите его.

Теперь, почему я должен защищать это, когда вам явно нравится LINQ? Простой: LINQ не дает никаких преимуществ для использования, а также вреден для производительности. Короче говоря, это неправильный инструмент для этой работы. Часть улучшения в использовании вещи - это знать, когда это нецелесообразно использовать.

+0

Согласен, LINQ может хорошо читать, но он создает так много проблем, скрывая, что код действительно делает от разработчика. Я видел, как люди используют отражение внутри запросов LINQ .... тьфу! –

Смежные вопросы