Почему Alibaba не рекомендует MySQL использовать текстовый тип?

Java база данных
Почему Alibaba не рекомендует MySQL использовать текстовый тип?

Есть чувства, есть галантерейные товары, поиск в WeChat【Третий принц Ао Бин] Обратите внимание на этого другого программиста.

эта статьяGitHub github.com/JavaFamilyВключено, и есть полные тестовые площадки, материалы и мой цикл статей для интервью с производителями первой линии.

предисловие

Как мы все знаем, MySQL широко используется в бизнес-системе OLTP (онлайн-обработка транзакций) в Интернете.

Ниже объясняется, почему текстовый тип не рекомендуется, и предлагаемый метод преобразования текста из структуры хранения текстового типа.

задний план

Запись таблицы журнала приводит к замедлению DML

описание проблемы

У мошенника есть бизнес-система, которая использует высокодоступную версию RDS для MySQL 5.7, настраивает long_query_time = 1 с и добавляет предупреждение о медленных запросах.Моя первая реакция — мошенник запутался.

Благодаря мониторингу я вижу, что CPU, QPS, TPS и другие показатели не очень высоки, в последнее время весь сайт Double Eleven занимается маркетинговой деятельностью, и количество пользователей немного увеличилось. Некая кривая обратная связь о том, что некоторые интерфейсы, которые не были медленными, стали очень медленными, что влияет на нормальную работу, и вам нужно заняться устранением неполадок.

анализ проблемы

Из предупреждения о медленных запросах я вижу, что некоторые операторы вставки и обновления выполняются относительно медленно.В то же время мониторинг периода предупреждения показывает, что IOPS очень высок, достигая около 70 МБ/с.Поскольку функция CloundDBA RDS недоступен, и нет функции журнала аудита, Устранение неполадок сложнее, поэтому я могу анализировать только бинлог.

Настроил max_binlog_size=512Мб, в период высоких IOPS смотреть генерацию бинлога.

Необходимо проанализировать, почему так быстро пишется бинлог, скорее всего причина в том, что на вставке в таблицу request_log стоит текстовый тип, структура таблицы request_log следующая (демо)

CREATE TABLE request_log (`
 `id bigint(20) NOT NULL AUTO_INCREMENT,`
 `log text,`    
 `created_at datetime NOT NULL,`
 `status tinyint(4) NOT NULL,`
 `method varchar(10) DEFAULT NULL,`
 `url varchar(50) DEFAULT NULL,`
 `update_at datetime DEFAULT NULL,`
 `running_time tinyint(4) DEFAULT '0',`
 `user_id bigint(20) DEFAULT NULL,`
 `type varchar(50) DEFAULT NULL,`
 `PRIMARY KEY (id)`
`) ENGINE=InnoDB AUTO_INCREMENT=4229611 DEFAULT CHARSET=utf8` 

Проанализируйте бинлог:

$ mysqlbinlog --no-defaults -v -v --base64-output=DECODE-ROWS mysql-bin.000539|egrep "insert into request_log"

Экран забит непонятным контентом, и долго его перелистывал.

По сути, было установлено, что это вызвано записью в поле журнала request_log, что приводит к частой очистке binlog_cache и чрезмерному переключению binlog, что приводит к высоким IOPS и влияет на другие обычные операции DML.

проблема решена

После общения со студентами-разработчиками планирую исправить эту проблему в следующей версии, больше не записывать информацию о запросе в таблицу, писать ее в локальный лог-файл, и извлекать в es через filebeat for query.Если вы просто хотите для просмотра журнала вы также можете получить доступ к GrayLog и т. д. Инструмент журнала, нет необходимости писать в базу данных.

В конце статьи я также представлю несколько связанных с MySQL ям, на которые я наступил.Прежде чем представить ямы, я сначала представлю тип MySQLText.

Текст в MySQL

Тип текста

текст — это большой объект, в котором может храниться большой объем данных. Существует четыре типа: МЕЛКИЙ ТЕКСТ, ТЕКСТ, СРЕДНИЙ ТЕКСТ, ДЛИННЫЙ ТЕКСТ. Различные типы хранят разные диапазоны значений, как показано ниже.

Data Type Storage Required
TINYTEXT L + 1 bytes, where L < 2**8
TEXT L + 2 bytes, where L < 2**16
MEDIUMTEXT L + 3 bytes, where L < 2**24
LONGTEXT L + 4 bytes, where L < 2**32

Где таблица L — это количество байтов фактической длины, хранящейся в текстовом типе. Можно подсчитать, что максимальная длина хранения типа TEXT составляет 2**16-1 = 65535 байт.

Страницы данных InnoDB

Страница данных Innodb состоит из следующих 7 частей:

содержание Занимаемый размер инструкция
File Header 38Bytes заголовок файла данных
Page Header 56 Bytes заголовок данных
Инфимун и Супермум Рекордс псевдозапись
User Records Данные пользователя
Free Space Свободное пространство: внутренняя структура представляет собой связанный список, после удаления запись будет добавлена ​​в связанный список free_lru.
Page Dictionary Словарь данных страницы: хранит записи об относительном расположении записей, также известный как слот, который представляет собой разреженный каталог внутри
File Trailer 8Bytes Конец файла: чтобы определить, была ли страница полностью записана на диск.

Описание: Трейлер файла имеет только одну часть FiL_Page_end_lsn, занимающую 8 байтов, первые 4 байта представляют собой значение контрольной суммы страницы, последние 4 байта и FIL_PAGE_LSN в заголовке файла, если страница повреждена, определяется трейлером файла. part, и обнаружение этой части будет иметь определенные накладные расходы.Пользователи могут включить или отключить обнаружение целостности этой страницы через параметр innodb_checksums.

Начиная с MySQL 5.6, механизмом хранения таблиц по умолчанию является InnoDB, который является ROW-ориентированным хранилищем.Каждая страница (размер страницы по умолчанию = 16 КБ), также указываются сохраненные записи строк, и максимум 16 КБ / 2 - 200 = 7992 строки. разрешено хранить.

Формат строки InnoDB

Innodb поддерживает четыре формата строк:

формат строки Особенности компактного хранения Расширенное хранилище столбцов переменной длины Поддержка больших префиксных индексов поддержка сжатия Поддерживаемые типы табличных пространств
REDUNDANT No No No No system, file-per-table, general
COMPACT Yes No No No system, file-per-table, general
DYNAMIC Yes Yes Yes No system, file-per-table, general
COMPRESSED Yes Yes Yes Yes file-per-table, general

Поскольку Dynamic является разновидностью Compact, структура аналогична.Теперь по умолчанию используется динамический формат;COMPRESSED в основном сжимает данные таблиц и индексов, что обычно подходит для малоиспользуемых требований к архивированию и резервному копированию.Мы в основном представляем REDUNDANT и COMPACT. формат линии.

Резервный формат линии

Этот формат предназначен для совместимости со старыми версиями MySQL.

Формат линейной записи:

Variable-length offset list record_header col1_value col2_value ……. text_value
список смещения длины поля Запись информации заголовка, занимающая 48 байт данные столбца 1 данные столбца 2 ……. Данные указателя текстового столбца

Имеет следующие характеристики:

  • Первые 768 байт столбцов переменной длины хранятся в записи индекса, а остальные хранятся на странице переполнения.Для столбцов фиксированной длины, превышающих 768 байт, они хранятся вне страницы как столбцы переменной длины.
  • Каждая запись на индексной странице содержит 6-байтовый заголовок, используемый для связывания записей для блокировки строк.
  • Записи кластеризованного индекса содержат все столбцы, определенные пользователем. Также имеется 6-байтовый идентификатор транзакции (DB_TRX_ID) и 7-байтовый столбец указателя сегмента отката (Roll pointer).
  • Если созданная таблица не отображает указанный первичный ключ, каждая строка кластеризованного индекса также включает 6-байтовое поле идентификатора строки (идентификатор строки).
  • Каждая запись вторичного индекса содержит все определенные столбцы индекса первичного ключа.
  • Запись содержит указатель на каждый столбец этой записи, если общая длина столбцов записи меньше 128 байт, этот указатель занимает 1 байт, иначе 2 байта. Этот массив указателей называется каталогом записи. Область, на которую указывает указатель, является частью данных этой записи.
  • Символьные поля фиксированной длины, такие как CHAR(10), хранятся в формате фиксированной длины с пробелами в конце.
  • Поля фиксированной длины, длина которых больше или равна 768 байтам, будут закодированы как поля переменной длины и сохранены вне страницы.
  • Значение SQL NULL хранит один или два байта в записи. Для полей переменной длины нулевое значение занимает 0 байт в области данных. Для полей фиксированной длины по-прежнему сохраняйте фиксированную длину в разделе данных, а резервирование пространства фиксированной длины для нулевых значений позволяет обновлять столбец с нулевого значения на ненулевое значение, не вызывая разделения индекса. .
  • Для типа varchar формат записи Redundant row также не занимает места для хранения, в то время как значение NULL типа CHAR требует места.

Среди них тип переменной длины хранится как длина + данные.Длина разных типов составляет от 1 до 4 байт (от L+1 до L+4).Для значения типа TEXT требуется L байт для хранения значение, и одновременно требуется 2 слова.Секция хранит длину значения. При этом максимальная длина строки Innodb указана как 65535 байт, для типа Text хранятся только указатели от 9 до 12 байт, а данные хранятся отдельно на странице переполнения.

Компактный формат строки

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

Формат линейной записи:

Variable-length field length list НУЛЕВОЙ флаг record_header col1_value col2_value ……. text_value
список длин полей переменной длины Запись информации заголовка - данные столбца 1 данные столбца 2 ……. Данные указателя текстового столбца

Заголовок Compact представляет собой список полей переменной длины, отличных от NULL, и размещается в порядке, обратном столбцам. Если длина столбца меньше 255 байт, он представлен 1 байтом, если больше 255 байт, это представлено 2 байтами. Максимальная длина поля переменной длины не может превышать 2 байта, поскольку максимальная длина типа varchar в базе данных MySQL ограничена 65 535. Вторая часть после поля переменной длины — это флаг NULL, указывающий, является ли строка данных имеет значение NULL. Если есть, то он представлен 1, и байт, занимаемый этой частью, должен быть 1 байт.

Поэтому при создании таблицы старайтесь использовать NOT NULL DEFAULT ''. Если столбец в таблице хранит большое количество значений NULL, это будет занимать место с одной стороны и влиять на стабильность столбца индекса с другой стороны .

Имеет следующие характеристики:

  • Каждая запись индекса содержит 5-байтовый заголовок, которому может предшествовать заголовок переменной длины. Этот заголовок используется для связывания связанных записей вместе, а также для блокировки строк.
  • Часть переменной длины заголовка записи содержит битовый вектор, представляющий нулевое значение. Если количество полей, допускающих значение NULL, в индексе равно N, этот битовый вектор содержит число байтов, округленное до N/8. Масштаб Если есть 9-16 полей, которые могут быть NULL, этот битовый вектор использует два байта. Столбец со значением NULL не занимает места, только биты в этом битовом векторе. Часть заголовка переменной длины также содержит длину поля переменной длины. Каждая длина занимает один или два байта, в зависимости от максимальной длины поля. Если все столбцы допускают значение NULL и указана фиксированная длина, в заголовке записи отсутствует часть переменной длины.
  • Для каждого поля переменной длины, которое не равно NULL, заголовок записи содержит однобайтовую или двухбайтовую длину поля. 2-байтовый заголовок записи используется только тогда, когда поле хранится во внешней области переполнения или когда максимальная длина поля превышает 255 байт, а фактическая длина превышает 127 байт. Соответствуя полю внешней памяти, длина в два байта указывает длину части внутренней памяти плюс 20-байтовый указатель на часть внешней памяти. Внутренняя часть составляет 768 байт, поэтому значение длины равно 768+20, а 20-байтовый указатель хранит реальную длину этого поля.
  • NULL не занимает никакого места в этой части, то есть NULL не занимает никакого места в фактической памяти, за исключением того, что он занимает бит флага NULL.
  • За заголовком записи следует часть данных непустых полей.
  • Записи кластеризованного индекса содержат все поля, указанные пользователем. Также имеется 6-байтовый столбец идентификатора транзакции и 7-байтовый указатель сегмента отката.
  • Если индекс первичного ключа не указан, кластеризованный индекс также включает 6-байтовый столбец Row ID.
  • Каждая запись вторичного индекса содержит столбец первичного ключа для всех вторичных индексов, в которых не определен ключ кластеризованного индекса. Если какой-либо из столбцов первичного ключа имеет переменную длину, каждая головная часть записи вторичного индекса имеет запись переменной длины для своей длины, даже если вторичный индекс определен в столбце фиксированной длины.
  • Символьные поля фиксированной длины, такие как CHAR(10), хранятся в формате фиксированной длины с пробелами в конце.
  • Для наборов символов переменной длины, таких как uft8mb3 и utf8mb4, InnoDB пытается сохранить CHAR(N) в N байтах. Если значение столбца CHAR(N) превышает N байтов в длину, пробелы после столбца сокращаются до минимального значения. Максимальная длина значения столбца CHAR(N) равна максимальному количеству кодировок символов x N. Например, самая длинная кодировка набора символов utf8mb4 — 4, а самое длинное количество байтов в столбце — 4*N.

Проблемы, вызванные типом Text

Вставка текстового поля приводит к ошибке

Создать тестовую таблицу

[root@barret] [test]>create table user(id bigint not null primary key auto_increment, 
  -> name varchar(20) not null default '' comment '姓名', 
  -> age tinyint not null default 0 comment 'age', 
  -> gender char(1) not null default 'M' comment '性别',
  -> info text not null comment '用户信息',
  -> create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  -> update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间'
  -> );
Query OK, 0 rows affected (0.04 sec)

Вставить тестовые данные

root@barret] [test]>insert into user(name,age,gender,info) values('moon', 34, 'M', repeat('a',1024*1024*3));
ERROR 1406 (22001): Data too long for column 'info' at row 1
[root@barret] [test]>insert into user(name,age,gender,info) values('sky', 35, 'M', repeat('b',1024*1024*5));
ERROR 1301 (HY000): Result of repeat() was larger than max_allowed_packet (4194304) - truncated

Анализ ошибок

[root@barret] [test]>select @@max_allowed_packet;
+----------------------+
| @@max_allowed_packet |
+----------------------+
|       4194304 |
+----------------------+
1 row in set (0.00 sec)

max_allowed_packet управляет максимальным размером коммуникационного буфера.Когда размер отправляемого пакета данных превышает это значение, будет сообщено об ошибке.Все мы знаем, что MySQL включает уровень сервера и механизм хранения, которые следуют протоколу 2PC.Сервер уровень в основном обрабатывает пользовательские запросы: запросы на подключение —> анализ синтаксиса SQL-> семантическая проверка-> создание плана выполнения-> план выполнения-> выборка данных; уровень механизма хранения в основном хранит данные и предоставляет интерфейсы чтения и записи данных.

max_allowed_packet=4M,当第一条insert repeat('a',1024*1024*3),数据包Server执行SQL发送数据包到InnoDB层的时候,检查数据包大小没有超过限制4M,在InnoDB写数据时,发现超过了Text的限制导致报错。第二条insert的数据包大小超过限制4M,Server检测不通过报错。

См. описание параметра в группе параметров AWS RDS.

max_allowed_packet: This value by default is small, to catch large (possibly incorrect) packets. Must be increased if using large TEXT columns or long strings. As big as largest BLOB.

Увеличение размера этого параметра может уменьшить ошибку, но не может полностью решить проблему.

Экземпляр RDS заблокирован

описание фона

Каждый месяц компания будет проводить некоторые маркетинговые мероприятия.Есть сервис apush activity push, который развернут отдельно в high-availability версии RDS для MySQL 5.7.Конфигурация 4C8G 150G disk, а в базе всего 4 таблицы Я ухожу с работы в 22:00 вечера. В то время данные экземпляра rds использовали 50G пространства. На следующее утро в 9:30 в метро я получил тревожное текстовое сообщение DingTalk, указывающее, что пуш-сервис rds Экземпляр был заблокирован с —только для чтения, потому что диск заполнен.Сообщалось о множестве ошибок MySQL.

анализ проблемы

Войдите в базу данных через DMS, посмотрите, какая таблица самая большая, и обнаружите, что есть таблица push_log, которая занимает 100G+.Глядя на структуру таблицы ниже, есть два текстовых поля.

request text default '' comment '请求信息',
response text default '' comment '响应信息'
mysql>show  table status like 'push_log';

Обнаружено, что Avg_row_length в основном составляет около 150 КБ, строк = 78 Вт, а размер таблицы составляет около 780000 * 150 КБ/1024/1024 = 111,5 ГБ.

Обновление через первичный ключ также медленно

insert into user(name,age,gender,info) values('thooo', 35, 'M', repeat('c',65535);
insert into user(name,age,gender,info) values('thooo11', 35, 'M', repeat('d',65535);
insert into user(name,age,gender,info) select name,age,gender,info from user;
Query OK, 6144 rows affected (5.62 sec)
Records: 6144  Duplicates: 0  Warnings: 0                                        
[root@barret] [test]>select count(*) from user;
+----------+
| count(*) |
+----------+
|    24576 |
+----------+
1 row in set (0.05 sec)

Выполните операцию обновления и отслеживайте.

mysql> set profiling = 1;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> update user set info = repeat('f',65535) where id = 11;
Query OK, 1 row affected (0.28 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> show profiles;
+----------+------------+--------------------------------------------------------+
| Query_ID | Duration   | Query                                                  |
+----------+------------+--------------------------------------------------------+
|        1 | 0.27874125 | update user set info = repeat('f',65535) where id = 11 |
+----------+------------+--------------------------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show profile cpu,block io for query 1;  
+----------------------+----------+----------+------------+--------------+---------------+
| Status               | Duration | CPU_user | CPU_system | Block_ops_in | Block_ops_out |
+----------------------+----------+----------+------------+--------------+---------------+
| starting             | 0.000124 | 0.000088 |   0.000035 |            0 |             0 |
| checking permissions | 0.000021 | 0.000014 |   0.000006 |            0 |             0 |
| Opening tables       | 0.000038 | 0.000026 |   0.000011 |            0 |             0 |
| init                 | 0.000067 | 0.000049 |   0.000020 |            0 |             0 |
| System lock          | 0.000076 | 0.000054 |   0.000021 |            0 |             0 |
| updating             | 0.244906 | 0.000000 |   0.015382 |            0 |         16392 |
| end                  | 0.000036 | 0.000000 |   0.000034 |            0 |             0 |
| query end            | 0.033040 | 0.000000 |   0.000393 |            0 |           136 |
| closing tables       | 0.000046 | 0.000000 |   0.000043 |            0 |             0 |
| freeing items        | 0.000298 | 0.000000 |   0.000053 |            0 |             0 |
| cleaning up          | 0.000092 | 0.000000 |   0.000092 |            0 |             0 |
+----------------------+----------+----------+------------+--------------+---------------+
11 rows in set, 1 warning (0.00 sec)

Видно, что основное время уходит на шаг обновления, количество вывода IO составляет 16392 раза, и обновление по id на параллельной таблице тоже станет очень медленным.

group_concat также вызовет ошибки запроса

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

select group_concat(dru_name) from t_drugstore group by province;

Встроенная функция group_concat возвращает агрегированную строку. Максимальная длина определяется параметром group_concat_max_len (максимально допустимая длина результата в байтах для GROUP_CONCAT()). Значение по умолчанию — 1024, что обычно слишком мало. Для разработки требуется большая длина , например 1024000.

Когда размер результирующего набора, возвращаемого group_concat, превышает предел max_allowed_packet, программа сообщит об ошибке, которая требует дополнительного внимания.

Встроенная таблица журнала MySQL

Таблицы журнала mysql.general_log и mysql.slow_log в MySQL, если включена функция аудита аудита и log_output=TABLE, будет таблица mysql.audit_log, структура аналогична mysql.general_log.

Взгляните на их структуру таблицы отдельно

CREATE TABLE `general_log` (
  `event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
  `user_host` mediumtext NOT NULL,
  `thread_id` bigint(21) unsigned NOT NULL,
  `server_id` int(10) unsigned NOT NULL,
  `command_type` varchar(64) NOT NULL,
  `argument` mediumblob NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
CREATE TABLE `slow_log` (
  `start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
  `user_host` mediumtext NOT NULL,
  `query_time` time(6) NOT NULL,
  `lock_time` time(6) NOT NULL,
  `rows_sent` int(11) NOT NULL,
  `rows_examined` int(11) NOT NULL,
  `db` varchar(512) NOT NULL,
  `last_insert_id` int(11) NOT NULL,
  `insert_id` int(11) NOT NULL,
  `server_id` int(10) unsigned NOT NULL,
  `sql_text` mediumblob NOT NULL,
  `thread_id` bigint(21) unsigned NOT NULL
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'

mysql.general_log записывает все SQL, обработанные MySQL Server, включая бэкенд и пользователя, вставки происходят часто, и в то же времяargumentmediumblob NOT NULL влияет на производительность MySQL Server. Как правило, для отслеживания и устранения проблем в среде разработки мы можем включить general_log. В производственной среде запрещено включать general_log, а audit_log можно включить. Он делает некоторые фильтры на основе general_log. Например, мне нужны только все SQL, инициированные бизнес-аккаунтом. Это очень полезно. Во многих случаях необходимо проанализировать, какой SQL имеет более высокие QPS и TPS в определенный период времени.

mysql.slow_log записывает все SQL, выполненные в течение long_query_time.Если следовать спецификации разработки MySQL, не будет слишком много медленных запросов, но если log_queries_not_using_indexes=ON включен, будет записано много SQL полного сканирования таблицы.При этом время, таблица slow_log будет очень большой. Большой, для RDS обычно сохраняются данные только за один день. При частой вставке в slow_log выполнение усечения таблицы slow_log для очистки slow_log вызовет MDL и повлияет на стабильность MySQL.

Рекомендуется установить log_output=FILE и включить slow_log и audit_log, чтобы slow_log и audit_log записывались в файлы, а эти файлы обрабатывались через Go API и данные записывались в распределенную колоночную базу данных clickhouse для статистического анализа. .

Предложения по преобразованию текста

использовать хранилище es

В MySQL общая таблица журнала будет хранить данные типа запроса или ответа в текстовом виде, который используется для ручного устранения неполадок при сбое вызова интерфейса, а частота использования очень низкая. Вы можете записать в локальный файл журнала, извлечь его в es через filebeat, проиндексировать по дням и очистить в соответствии с политикой хранения данных.

Используйте объектное хранилище

Некоторые таблицы бизнес-сценариев используют типы TEXT и BLOB и хранят некоторую информацию об изображениях, например изображения продуктов, и частота обновления относительно низкая.Вы можете рассмотреть возможность использования объектного хранилища, такого как OSS от Alibaba Cloud и S3 от AWS, которые могут быть удобными и эффективно удовлетворить такие потребности.

Суммировать

Поскольку MySQL является однопроцессорной многопоточной моделью, оператор SQL не может выполняться несколькими ядрами ЦП, что определяет, что MySQL больше подходит для OLTP (особенности: большое количество обращений пользователей, логическое чтение, сканирование индекса, возврат небольшое количество данных, SQL прост) Для бизнес-систем некоторые спецификации моделирования и спецификации разработки должны быть сформулированы для MySQL, и следует максимально избегать текстового типа.Он не только потребляет много пропускной способности сети и ввода-вывода, но также операции DML над таблицей станут очень медленными.

Кроме того, рекомендуется перенести сложный статистический анализ SQL в хранилище данных OLAP в реальном времени. Например, в настоящее время используются clickhouse, Liyun ADB и AWS Redshift, чтобы можно было разделить бизнес-SQL OLTP и OLAP для обеспечения стабильности. системы бизнеса.

Ладно, на этом все. Меня зовут Ао Бин. Чем больше вы знаете, тем больше вы не знаете. Увидимся в следующем выпуске!

Я Ао Бин,Чем больше вы знаете, тем больше вы не знаете, спасибо за ваши таланты:как,собиратьиКомментарий, увидимся в следующий раз!


Статья постоянно обновляется, вы можете искать в WeChat "Третий принц Ао Бин"Прочтите это в первый раз, ответьте [материал] Подготовленные мной материалы интервью и шаблоны резюме крупных заводов первой линии, эта статьяGitHub github.com/JavaFamilyОн был включен, и есть полные тестовые сайты для интервью с крупными заводами.Добро пожаловать в Star.