ускорить операцию ОБНОВЛЕНИЯ

Пожалуйста, помогите мне ускорить операцию UPDATE в таблице. Таблица имеет уникальный идентификатор, который используется для поиска записи и ОБНОВЛЕНИЯ ее полей. В таблице 1 млн записей. Индекс не используется. Только уникальный идентификатор. Вставка занимает некоторое время... где я ожидал миллисекунды.

Структура таблицы:

create table customers
(
    id int IDENTITY(1,1) UNIQUE NOT NULL,
    phonenum varchar(15) UNIQUE NOT NULL,
    date datetime,
    company varchar(150),
    full_name varchar(150),
    address varchar(150),   
    street varchar(100),
    zip varchar(100),
    city varchar(100),
    info varchar(300),
    op_data varchar(150),
    op_date datetime,
    op_user_taken varchar(100),
    op_time_taken  datetime,
    op_status varchar(100),
    user_taken varchar(100),
    time_taken  datetime,
    status varchar(100),        
    );

Я использую метод SqlConnection System.Data.SqlClient.SqlConnection и ExecuteNonQuery для ОБНОВЛЕНИЯ записи.

Нужно ли переделывать мою таблицу или ExecuteNonQuery работает так медленно?

РЕДАКТИРОВАТЬ: Команда обновления:

"UPDATE customers SET user_taken=@param1, time_taken=@param2,
 date=@param3, company=@param4, full_name=@param55,
 address=@param6, street=@param8, zip=@param9,
 city=@param10, info=@param11 , status=\'Completed\',
op_data=@param12 WHERE id=@param7";

person MichaelVerossa    schedule 29.07.2011    source источник
comment
Можем ли мы увидеть пример инструкции UPDATE?   -  person n8wrl    schedule 30.07.2011
comment
Покажите нам свое заявление об обновлении. Если вы обновляете все 1 млн строк, то да, это займет некоторое время.   -  person Tomas Voracek    schedule 30.07.2011
comment
Если вы ожидаете, что это произойдет за миллисекунды, добавьте несколько индексов? Если ему нужно выполнить полное сканирование таблицы с 1 миллионом записей, не ожидайте, что он будет быстрым. :п   -  person Dismissile    schedule 30.07.2011
comment
Нет, конечно. Сначала требуется бесплатная запись, заблокируйте ее. А затем обновляет его, зная его ID. Не все записи 1M. За одну операцию обновляется только одна запись.   -  person MichaelVerossa    schedule 30.07.2011
comment
Если у вас нет индекса в таблице, ему все равно придется сканировать всю таблицу, чтобы найти запись, которую необходимо обновить. Добавьте индекс.   -  person Dismissile    schedule 30.07.2011
comment
Каков тип данных @param7 и как выглядит план выполнения?   -  person Martin Smith    schedule 30.07.2011


Ответы (3)


Сделайте столбец идентификатора первичным ключом. Первичные ключи автоматически становятся индексом. Если вы используете простой оператор обновления, такой как:

UPDATE customers SET <something> WHERE id = @id 

Тогда это должно запустить INDEX SEEK и быть намного быстрее. Без этого индекса вы обновляете с помощью TABLE SCAN, который занимает на несколько порядков больше времени, чем INDEX SEEK или даже INDEX SCAN (что может произойти, если вы обновляете большое количество строк).

Еще одна хитрость заключается в том, чтобы взять оператор обновления, запустить его в SQL Server и просмотреть план выполнения. Это скажет вам, где узкое место. Кроме того, вы можете перейти к Параметры запроса | Расширенный | и установите статистику для отображения на вкладке вывода.

person Josh    schedule 29.07.2011
comment
Полностью согласен, для этого и нужны индексы. - person Chris Haas; 30.07.2011
comment
PRIMARY KEY и UNIQUE — это и ограничения, и индексы! - person a1ex07; 30.07.2011
comment
Да, но ограничение UNIQUE нельзя сделать кластеризованным. Ему также потребуется добавить кластеризованный индекс поверх ограничения UNIQUE, чтобы добиться лучшего индекса для больших объемов данных. - person Josh; 30.07.2011
comment
Неправда, что его нельзя сделать кластерным. CREATE TABLE customers(id INT IDENTITY(1,1) UNIQUE CLUSTERED NOT NULL) совершенно верно. Опубликованный DDL сможет использовать NCI, неявно созданный уникальным ограничением, а затем выполнить поиск по закладкам, чтобы найти строку для обновления. Не супер, но и не катастрофично. - person Martin Smith; 30.07.2011

Я думаю, это потому, что у вас нет кластеризованного индекса (unique по умолчанию не кластеризован), поэтому SQL Server использует некластеризованный индекс в куче, чтобы найти вашу запись для обновления (UNIQUE - это индекс). Id должен быть первичным ключом (который по умолчанию сгруппирован), а не UNIQUE.

person a1ex07    schedule 29.07.2011

Пытаться -

using (SqlCommand comm = new SqlCommand("update sql", conn))
{
      SqlDataReader results = (SqlDataReader)comm.ExecuteReader();
}

Просто любопытно...

person Ross Barbish    schedule 29.07.2011
comment
Зачем ExecuteReader() запускать команду UPDATE? Можете ли вы объяснить, почему вы думаете, что этот подход будет быстрее? - person Aaron Bertrand; 30.07.2011