Самый эффективный способ получить все данные из таблицы SQL Server со столбцом varchar (max) - PullRequest
1 голос
/ 01 октября 2009

Этот вопрос для SQL Server 2005.

У меня есть таблица с 2 столбцами.

Table_A
    Id Guid (PrimaryKey)
    TextContent varchar(max)

Таблица содержит около 7000 записей и текстового диапазона в диапазоне от 0 до 150K +.

Когда я делаю оператор выбора SELECT Id, TextContent FROM Table_A , это заняло очень много времени, около 10 минут.

Есть ли лучший способ получить все данные из таблицы?

Во время основного исполнения я загружаю только определенные записи. Пример: SELECT Id, TextContent FROM TableA WHERE ID IN (@ id0, @ id1, @ id2, @ id3 .... @ id20) . Этот запрос не медленный, но и не очень быстрый. Я хочу посмотреть, смогу ли я оптимизировать процесс, потянув TextContent раньше времени выполнения. Это нормально для выполнения этого процесса через минуту или две, но 10 минут не приемлемо.

Ответы [ 6 ]

2 голосов
/ 02 октября 2009

GUID является первичным ключом, который также по умолчанию будет вашим ключом кластеризации, без сомнения будет вызывать большую фрагментацию - но, учитывая характер столбцов, varchar (max) будет регулярно отключаться от страницы в Хранение больших объектов и не хранится на странице, если оно не подходит, оставаясь в пределах ограничения 8060.

Таким образом, фрагментация не поможет при наличии GUID в качестве основного, если вы также сделали его кластеризованным - вы можете проверить уровни фрагментации с помощью DMV sys.dm_db_index_physical_stats

Я бы не думал, что фрагментация - это действительно проблема, если средний объем данных на строку не высок, например регулярно выше 8к.

Если это так, ... фрагментация начинает болеть. В худшем случае это 1 строка на страницу, 7 тыс. Операций ввода-вывода, что не является идеальным, но при среднем 100 тыс. На хранилище больших объектов можно рассмотреть дополнительные 87 тыс. Операций ввода-вывода, и порядок записи данных и т. Д. Может привести к тому, что Предполагается, что это будет последовательное сканирование таблицы (и диска), превращающееся в массовый случайный ввод-вывод, когда диск перемещается вперед и назад между страницей с указателем строки + LOB и страницами LOB. К этому добавляется вероятность того, что GUID является ключом кластеризации, поэтому он не может даже сканировать страницы данных без небольшого движения головки диска.

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

Я знаю, что вы пытаетесь предварительно кэшировать данные, которые могут работать время от времени - но они выполняются на таком большом объекте, это указывает на то, что что-то еще не так, и вы исправляете неправильную проблему.

A.

1 голос
/ 02 октября 2009

Ваш столбец идентификатора является GUID. Вы используете по умолчанию? Это NewID ()? Я предполагаю, что это кластеризовано на ПК.

Если вы по умолчанию используете NewSequentialID (), вы получите меньше разбиений страниц, поэтому ваши данные будут распределены по меньшему количеству физических страниц.

С таким огромным количеством данных, это единственное, что я могу увидеть, что может повысить производительность.

1 голос
/ 01 октября 2009

Это правильный способ извлечения данных из таблицы, если только вам не нужна только 1 строка. Если вам нужна только 1 строка, просто используйте правильный запрос.

Какой тип сетевого подключения вы используете? Скажем так, у вас есть 7000 записей. Каждый из них содержит в среднем 100 тыс. Данных (для простоты, если это больше или меньше, это нормально, моя точка зрения остается в силе) Всего запрос вернет 700 МБ данных! Даже при очень быстром соединении, это легко 10 минут времени загрузки.

Даже при совершенном 100-мегабитном соединении передача займет около минуты! Кроме того, вы должны извлечь эти данные с физического диска, что дополнительно займет некоторое время.

Я бы порекомендовал сделать какую-то подкачку, чтобы брать данные небольшими кусочками.

1 голос
/ 01 октября 2009

Я сомневаюсь в этом. Если вы хотите «извлечь все данные из таблицы», вам необходимо прочитать каждый байт, хранящийся в таблице, и для этого может потребоваться много операций ввода-вывода с физического диска.

Возможно, вы хотите получить только некоторые данные из таблицы?

0 голосов
/ 02 октября 2009

Как уже упоминалось, вы получаете много данных. Сначала убедитесь, что вам действительно нужны все строки.

Если вы это сделаете, не извлекайте все сразу - используйте вместо этого LIMIT. Это на самом деле уменьшит скорость, но если что-то не получится, вам нужно будет только загрузить короткий бит снова и не ждать еще 10 минут.

SELECT Id, TextContent FROM Table_A LIMIT 0, 30

Этот запрос будет извлекать первые 30 записей вашей таблицы. С

SELECT Id, TextContent FROM Table_A LIMIT 30, 30

вы получите следующий кусок.

Может быть, вы могли бы предоставить нам немного больше информации, например, что вы хотите делать с данными и какой язык программирования вы используете?

0 голосов
/ 01 октября 2009

Да

1) никогда не используйте SELECT *, всегда перечисляйте ваши столбцы, 1, 2 или 100 2) попробуйте заглянуть в индексы

150 тыс. Символов? в этой области? Это то, что вы имеете в виду?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...