Выполнение вставки или обновления (upsert) на сервере SQL Server Compact Edition - PullRequest
2 голосов
/ 08 апреля 2009

У меня есть проект c #, который использует sqlserver Compact Edition и Entity Framework для доступа к данным. У меня есть необходимость вставить или обновить большое количество строк, 5000+ или более в БД, поэтому, если ключ существует, обновите запись, если не вставьте ее. Я не могу найти способ сделать это с компактной версией и EF без ужасной производительности, то есть за 2 минуты плюс на компьютере с ядром i7. Я попытался найти запись, чтобы увидеть, существует ли она, затем вставить, если нет, или обновить, если это так, поиск является убийцей в этом. Я попытался составить поисковый запрос, и это дало лишь небольшое улучшение. Еще одна вещь, которую я попробовал, это вставить запись в попытку и, если она не обновляется, но это заставляет меня сохранять изменения в каждой записи, чтобы получить исключение, а не в конце, что является причиной снижения производительности. Очевидно, я не могу использовать хранимые процедуры, потому что это компактная версия. Также я рассмотрел просто выполнение t-sql напрямую как-то на БД, но отсутствие операторов процесса в компакте, кажется, исключает это. Я искал по всему миру идеи. Я действительно хотел использовать компактный, если я могу чрезмерно выразить преимущества развертывания и возможность предотвращения пользователя копаться в БД. Будем благодарны за любые предложения.

Спасибо

Ответы [ 7 ]

6 голосов
/ 30 июня 2009

Когда мы используем SQL CE (и SQL 2005 Express в этом отношении), мы всегда сначала вызываем обновление, а затем вызываем вставку, если обновление дает число строк 0. Это очень просто реализовать и не требует Затраты попробуйте .. поймать блоки для потока управления.

2 голосов
/ 24 апреля 2009

Я бы порекомендовал использовать SqlCeResultSet напрямую. Вы теряете прекрасную безопасность типов EF, но производительность невероятно высока . Мы перешли с TypeDataSets в стиле ADO.NET 2.0 на SqlCeResultSet и SqlCeDataReader и увидели увеличение скорости в 20-50 раз.

2 голосов
/ 09 апреля 2009

Я не уверен, возможно ли это или нет, так как я не использовал Entity Framework, но вы пытались сначала запустить обновление и проверить количество строк - вставить, если строки не были обновлены? Это может быть быстрее, чем ловить исключения. Обычно плохая практика - использовать исключения для потока управления, и часто это сильно замедляет работу.

Если вы можете написать SQL напрямую, то самый быстрый способ сделать это - собрать все данные во временную таблицу, а затем обновить то, что существует, и вставить остатки (как в примере Андреа Бертани выше). Вы должны получить несколько лучшие результаты, используя левое объединение исходной таблицы в элементе выбора в вставке и исключая любые строки со значениями из исходной таблицы, которые не равны нулю:

INSERT INTO original
SELECT * FROM temp
LEFT JOIN original ON original.id = temp.id
WHERE original.id IS NULL
2 голосов
/ 09 апреля 2009

Может быть, вы могли бы получить результат, который вы ищете, с помощью простых запросов. Допустим, таблица, в которую вы хотите вставить или обновить, выглядит так:

TABLE original
     id integer,
     value char(100)

сначала вы можете создать временную таблицу с новыми значениями (вы можете использовать SELECT INTO или другие способы ее создания)

TABLE temp
    id integer,
    value char(100)

Теперь вам нужно сделать две вещи, обновить строки в оригинале и затем вставить новые значения

UPDATE original 
SET original.value = temp.value
FROM original, temp
WHERE original.id = temp.id

INSERT INTO original 
SELECT * from temp 
WHERE temp.id not IN (select o.id from original o)
2 голосов
/ 08 апреля 2009

Учитывая вашу проблему, я собираюсь предположить, что это программное обеспечение предполагает относительно жесткую среду. Рассматривали ли вы задачу определения sqlce и делать это самостоятельно? По сути, получить отсортированный список всех идентификаторов (ключей?) Из соответствующей таблицы и проверить каждый ключ объекта по этому списку, прежде чем поставить его в очередь для вставки?

Это делает несколько предположений, которые были бы плохими новостями для типичной БД, но с которыми вы, вероятно, можете обойтись в sqlce. Например, предполагается, что строки не будут вставлены или существенно изменены другим пользователем во время выполнения этой вставки.

Если список ключей слишком длинный, чтобы его можно было хранить в памяти для такой проверки, боюсь, я бы сказал, что sqlce просто не может быть подходящим инструментом для этой работы. (

1 голос
/ 30 июня 2009

См. SqlCeResultSet. Для проекта .NETCF я удалил почти весь SQL-код в пользу этого класса. Просто найдите "SqlCeResultSet" здесь и msdn.

Краткий обзор:

  1. Открыть результирующий набор. Если вам нужен поиск (для проверки существования), вам нужно будет предоставить индекс для набора результатов.

  2. Ищите набор результатов и читайте, чтобы проверить, нашли ли вы строку. Это очень быстро даже для таблиц с десятками тысяч строк (потому что поиск использует индекс).

  3. Вставить или обновить запись (см. SqlCeResultSet.NewRecord).


Мы успешно разработали проект с базой данных sqlce с основной таблицей продуктов, содержащей более 65000 строк (чтение / запись с 4 индексами).

0 голосов
/ 24 апреля 2009

SQL Server compact edition находится на ранней стадии разработки. Кроме того, в зависимости от вашего устройства доступ к диску памяти может быть довольно медленным, а SQLCE plus. Лучше всего работает с довольно статичным хранилищем данных.

Я предлагаю вам использовать более легкий API или рассмотреть SQLite.

...