Я унаследовал некоторые базы данных SQL Server. Существует одна таблица (я назову «G»), с примерно 86,7 миллионами строк и шириной 41 столбец, из исходной базы данных (я назову «Q») в SQL Server 2014 Standard, которая передает ETL в целевая база данных (я назову «P») с тем же именем таблицы в SQL Server 2008 R2 Standard.
то есть [Q]. [G] ---> [P]. [G]
РЕДАКТИРОВАТЬ: 20.03.2017: Некоторые люди спрашивали, является ли исходная таблица ЕДИНСТВЕННЫМ источником для целевой таблицы. Да, это единственный источник. Что касается ETL, то никаких реальных преобразований не происходит; фактически он предназначен для копирования исходных данных 1: 1. Поэтому не планируется добавлять дополнительные источники в эту целевую таблицу.
Чуть более половины столбцов в [Q]. [G] - это VARCHAR (исходная таблица):
- 13 колонн VARCHAR (80)
- 9 столбцов VARCHAR (30)
- 2 из столбцов VARCHAR (8).
Аналогично, те же столбцы в [P]. [G] являются NVARCHAR (целевой таблицей) с одинаковым количеством столбцов одинаковой ширины. (Другими словами, такой же длины, но NVARCHAR).
- 13 из столбцов НВАРЧАР (80)
- 9 из столбцов являются NVARCHAR (30)
- 2 из столбцов являются NVARCHAR (8).
Это не мой дизайн.
Я хотел бы изменить тип данных столбцов [P]. [G] (целевой) от NVARCHAR до VARCHAR. Я хочу сделать это безопасно (без потери данных при конвертации).
Как я могу посмотреть на значения данных в каждом столбце NVARCHAR в целевой таблице, чтобы подтвердить, действительно ли столбец содержит какие-либо данные Unicode?
Запрос (DMV?), Который может проверять каждое значение (в цикле?) Каждого столбца NVARCHAR и сообщать мне, является ли ЛЮБОЙ из значений подлинным Unicode, был бы идеальным решением, но приветствуются другие методы.
источник
[G]
ETLed для[P]
. Если[G]
это такvarchar
, и процесс ETL является единственным способом ввода данных[P]
, то, если процесс не добавляет истинные символы Юникода, их не должно быть. Если другие процессы добавляют или изменяют данные[P]
, вам нужно быть более осторожными - просто потому, что все текущие данные могут бытьvarchar
, не означает, чтоnvarchar
данные не могут быть добавлены завтра. Точно так же возможно, что все, что потребляет данные,[P]
нуждается вnvarchar
данных.Ответы:
Предположим, что один из ваших столбцов не содержит данных Unicode. Чтобы убедиться, что вам нужно будет прочитать значение столбца для каждой строки. Если у вас нет индекса по столбцу, с таблицей хранилища строк вам нужно будет прочитать каждую страницу данных из таблицы. Имея это в виду, я думаю, что имеет смысл объединить все проверки столбцов в один запрос к таблице. Таким образом, вы не будете много раз читать данные таблицы, и вам не придется кодировать курсор или какой-либо другой цикл.
Чтобы проверить один столбец, верьте, что вы можете просто сделать это:
Приведение из
NVARCHAR
вVARCHAR
должно дать вам тот же результат, за исключением случаев, когда есть символы Юникода. Символы Юникода будут преобразованы в?
. Поэтому приведенный выше код долженNULL
правильно обрабатывать случаи. У вас есть 24 столбца для проверки, поэтому вы проверяете каждый столбец в одном запросе с помощью скалярных агрегатов. Одна реализация ниже:Для каждого столбца вы получите результат,
1
если любое из его значений содержит юникод. Результат0
означает, что все данные могут быть безопасно преобразованы.Я настоятельно рекомендую сделать копию таблицы с новыми определениями столбцов и скопировать туда ваши данные. Вы будете делать дорогостоящие преобразования, если сделаете это на месте, поэтому создание копии может быть не намного медленнее. Наличие копии означает, что вы можете легко проверить, что все данные все еще там (одним из способов является использование ключевого слова EXCEPT ), и вы можете отменить операцию очень легко.
Также имейте в виду, что в настоящее время у вас могут отсутствовать данные Юникода, возможно, что в будущем ETL может загрузить Юникод в ранее чистый столбец. Если в вашем процессе ETL нет проверки на это, вам следует рассмотреть возможность добавления этого перед выполнением этого преобразования.
источник
NVARCHAR
столбец вNVARCHAR
тот тип, который уже есть. И не уверен, как вы определили необратимый символ, но вы можете конвертировать столбец в,VARBINARY
чтобы получить последовательности байтов UTF-16. И UTF-16 - это обратный порядок байтов, поэтомуp
=0x7000
и затем вы обращаете эти два байта в обратном порядке, чтобы получить кодовую точкуU+0070
. Но если источником является VARCHAR, то это не может быть символ Unicode. Что-то еще происходит. Нужно больше информации.VARCHAR
будет неявно преобразовываться вNVARCHAR
нее, но это может быть лучшеCONVERT(NVARCHAR(80), CONVERT(VARCHAR(80), column)) <> column
.SUBSTRING
иногда работает, но не работает с дополнительными символами, когда используются сопоставления, которые не заканчиваются_SC
, а тот, который использует Джон, - нет, хотя вряд ли проблема здесь. Но преобразование в VARBINARY всегда работает. ИCONVERT(VARCHAR(10), CONVERT(NVARCHAR(10), '›'))
не приводит?
, поэтому я хотел бы видеть байты. Процесс ETL, возможно, преобразовал это.Прежде чем что-то делать, рассмотрите вопросы, заданные @RDFozz в комментарии к вопросу, а именно:
Если ответ не соответствует «Я на 100% уверен, что это единственный источник данных для этой таблицы назначения», то не вносите никаких изменений, независимо от того, могут ли данные, находящиеся в настоящий момент в таблице, быть преобразованы без потеря данных.
И я хотел бы добавить , связанный с этим вопрос: Был ли какой - либо дискуссия вокруг поддержки нескольких языков в источнике тока таблице (то есть
[Q].[G]
) путем преобразования его вNVARCHAR
?Вам нужно будет спросить вокруг, чтобы получить представление об этих возможностях. Я предполагаю, что в настоящее время вам не сказали ничего, что указывало бы в этом направлении, иначе вы бы не задавали этот вопрос, но если предполагается, что эти вопросы - «нет», то их нужно задать и попросить достаточно широкая аудитория, чтобы получить максимально точный / полный ответ.
Основной проблемой здесь является не столько наличие кодовых точек Unicode, которые не могут быть преобразованы (когда-либо), но еще и наличие кодовых точек, которые не все помещаются на одной кодовой странице. Это хорошая вещь в Unicode: он может содержать символы из ВСЕХ кодовых страниц. Если вы конвертируете из
NVARCHAR
- где вам не нужно беспокоиться о кодовых страницах - вVARCHAR
, то вам нужно будет убедиться, что в столбце Сортировка назначения используется та же кодовая страница, что и в исходном столбце. Это предполагает наличие либо одного источника, либо нескольких источников, использующих одну и ту же кодовую страницу (хотя не обязательно один и тот же Collation). Но если есть несколько источников с несколькими кодовыми страницами, вы можете столкнуться со следующей проблемой:Возвращает (второй набор результатов):
Как видите, все эти символы можно преобразовать
VARCHAR
, но не в одномVARCHAR
столбце.Используйте следующий запрос, чтобы определить кодовую страницу для каждого столбца исходной таблицы:
ЧТО, КАК ГОВОРИТСЯ....
Вы упомянули, что находитесь на SQL Server 2008 R2, НО, вы не сказали, что такое Edition. Если вы оказались в Enterprise Edition, то забудьте обо всех этих вещах (поскольку вы, вероятно, делаете это просто для экономии места) и включите сжатие данных:
Реализация сжатия Unicode
Если вы используете Standard Edition (а теперь кажется, что вы 😞), то есть еще одна возможность: «Обновление до SQL Server 2016, поскольку SP1 включает в себя возможность для всех выпусков использовать сжатие данных (помните, я уже говорил« долгосрочный »). "😉).
Конечно, теперь, когда только что было разъяснено, что существует только один источник данных, вам не о чем беспокоиться, так как источник не может содержать символы только для Unicode или символы вне своего конкретного кода. стр. В этом случае единственное, о чем вам следует помнить, - это использовать тот же Collation, что и в исходном столбце, или хотя бы тот, который использует ту же кодовую страницу. Это означает, что если исходный столбец использует
SQL_Latin1_General_CP1_CI_AS
, то вы можете использоватьLatin1_General_100_CI_AS
в месте назначения.Как только вы узнаете, какой Collation использовать, вы можете:
ALTER TABLE ... ALTER COLUMN ...
бытьVARCHAR
(обязательно укажите текущийNULL
/NOT NULL
параметр), который требует немного времени и много места в журнале транзакций для 87 миллионов строк, ИЛИСоздайте новые столбцы «ColumnName_tmp» для каждого и медленно заполняйте,
UPDATE
делаяTOP (1000) ... WHERE new_column IS NULL
. После того, как все строки заполнены (и проверено, что все они скопированы правильно! Вам может понадобиться триггер для обработки UPDATE, если они есть), в явной транзакции используйтеsp_rename
для замены имен столбцов «текущих» столбцов на « _Old ", а затем новые столбцы" _tmp ", чтобы просто удалить" _tmp "из имен. Затем вызовитеsp_reconfigure
таблицу, чтобы сделать недействительными любые кэшированные планы, ссылающиеся на таблицу, и, если есть какие-либо представления, ссылающиеся на таблицу, вам нужно будет вызватьsp_refreshview
(или что-то в этом роде). После того, как вы проверили приложение и ETL правильно работает с ним, вы можете удалить столбцы.источник
Latin1_General_100_CI_AS
порядок сортировки, даже если он намного лучше, чем тот, который вы используете. Это просто означает, что сортировка и сравнение между ними будут одинаковыми, даже если они не будут такими же хорошими, как в новом сопоставлении, о котором я только что говорил.У меня есть некоторый опыт с этим, когда у меня была настоящая работа. Поскольку в то время, когда я хотел сохранить базовые данные, и мне также приходилось учитывать новые данные, которые могли содержать символы, которые могли бы быть потеряны в случайном порядке, я использовал непостоянный вычисляемый столбец.
Вот быстрый пример использования копии базы данных суперпользователя из дампа данных SO .
Мы сразу видим, что существуют DisplayNames с символами Unicode:
Итак, давайте добавим вычисляемый столбец, чтобы выяснить, сколько! Столбец DisplayName есть
NVARCHAR(40)
.Количество возвращает ~ 3000 строк
План выполнения, однако, немного затруднителен. Запрос заканчивается быстро, но этот набор данных не очень большой.
Поскольку вычисляемые столбцы не нужно сохранять для добавления индекса, мы можем сделать одно из них:
Что дает нам немного более аккуратный план:
Я понимаю , если это не ответ, так как она включает в себя архитектурные изменения, но учитывая размер данных, вы , вероятно , глядя на добавление индексов , чтобы справиться с запросами, самостоятельно присоединиться к таблице в любом случае.
Надеюсь это поможет!
источник
Используя пример в разделе Как проверить, содержит ли поле данные Unicode , вы можете прочитать данные в каждом столбце и выполнить
CAST
проверку ниже:источник