содержание
1. Нормативные основы и цель
2. Технические характеристики конструкции
2.1 Дизайн базы данных 2.1.1 Имя библиотеки 2.1.2 Структура таблицы 2.1.3 Оптимизация типа данных столбца 2.1.4 Дизайн указателя 2.1.5 Подбаза данных, подтаблица, таблица разделов 2.1.6 Набор символов 2.1.7 Предложения по дизайну для программного уровня DAO 2.1.8 Пример канонического оператора построения таблицы 2.2 Написание SQL 2.2.1 Операторы DML 2.2.2 Объединение нескольких таблиц 2.2.3 Транзакции 2.2.4 Сортировка и группировка 2.2.5 Операторы SQL, запрещенные в сети
1. Нормативные основы и цель
По сравнению с базами данных, такими как Oracle и SQL Server, база данных MySQL имеет преимущества и недостатки в своем ядре. Когда мы используем базу данных MySQL, нам нужно следовать определенным спецификациям и избегать слабых мест. Эта спецификация призвана помочь или направить технический персонал, такой как RD, QA, OP и т. Д., Чтобы сделать структуру базы данных подходящей для онлайн-бизнеса. Стандартизируйте изменения базы данных и процедуры обработки, дизайн таблиц базы данных, написание SQL и т. д., чтобы гарантировать стабильную и надежную работу бизнес-системы компании.
2. Технические характеристики конструкции
2.1 Дизайн базы данных
Все следующие спецификации будут отмечены в соответствии с тремя уровнями [высокий риск], [обязательный] и [рекомендуемый], а приоритет соответствия будет от высокого к низкому.
Для проектов, которые не соответствуют двум уровням [высокий риск] и [обязательный], администратор базы данных вызовет обратный вызов и потребует модификации.
2.1.1 Имя библиотеки
- [Обязательно] Имя библиотеки должно содержать не более 32 символов, а отношение соединения между именами таблиц и именами таблиц связанных модулей, таких как таблица пользователей и таблица user_login, должно быть показано как можно подробнее.
- [Обязательно] Формат имени библиотеки: имя бизнес-системы_имя подсистемы, а имена таблиц, используемые в одном модуле, должны максимально использовать унифицированный префикс.
- [Обязательно] Общий формат именования имен подбаз данных — это библиотечный подстановочный знак имя_номер, и число увеличивается с 0. Например, формат имени wenda_001 для подбиблиотеки по времени — «подстановочный знак библиотеки имя_время».
- [Обязательно] Набор символов должен быть явно указан при создании базы данных, и набор символов может быть только utf8 или utf8mb4. Создать базу данных Пример SQL: создать базу данных набор символов по умолчанию db1 utf8;.
2.1.2 Структура таблицы
- [Обязательно] Длина имен таблиц и столбцов не должна превышать 32. В именах таблиц могут использоваться только буквы, цифры и символы подчеркивания, и все они должны быть строчными.
- [Обязательно] Имя таблицы требует, чтобы имя модуля было тесно связано. Например, в системе учителя в качестве префикса используется «sz», а в системе канала — «qd» в качестве префикса.
- [Обязательно] При создании таблицы необходимо явно указать набор символов utf8 или utf8mb4.
- [Обязательно] При создании таблицы необходимо явно указать тип механизма хранения таблиц, если нет особых требований, то всегда будет InnoDB. Когда необходимо использовать механизм хранения, отличный от InnoDB/MyISAM/Memory, он должен быть проверен администратором баз данных, прежде чем его можно будет использовать в производственной среде. Поскольку таблица Innodb поддерживает важные функции реляционных баз данных, такие как транзакции, блокировки строк, восстановление после сбоев и MVCC, она является наиболее используемой системой хранения MySQL в отрасли. Это то, чего нет в большинстве других механизмов хранения, поэтому InnoDB — первый выбор.
- [Обязательно] При создании таблицы должен быть комментарий
- [Предложение] О первичном ключе при создании таблицы: (1) Обязательно, чтобы первичный ключ был id, типом был int или bigint, и это было auto_increment (2) Поле, которое идентифицирует основную часть каждой строки в таблицу не следует устанавливать в качестве первичного ключа.Рекомендуется установить для нее другие поля, такие как user_id , order_id и т. д., и создать индекс уникального ключа (см. дизайн таблицы cdb.teacher). Потому что, если он установлен в качестве первичного ключа, а значение первичного ключа вставлено случайным образом, это вызовет внутренние разбиения страниц innodb и множество случайных операций ввода-вывода, а производительность снизится.
- [Предложение] Основные таблицы (например, пользовательские таблицы и таблицы, связанные с деньгами) должны иметь поле времени создания create_time данных строки и поле времени последнего обновления update_time, что удобно для проверки проблем.
- [Предложение] Все поля в таблице должны быть НЕ NULL, компания может определить значение DEFAULT по мере необходимости. Потому что использование значений NULL вызовет такие проблемы, как дополнительное место для хранения каждой строки, подверженный ошибкам перенос данных и отклонение результатов расчета агрегатной функции.
- [Предложение] Рекомендуется вертикально разделить большие поля, такие как большие двоичные объекты и текст в таблице, на другие таблицы и выбирать только тогда, когда эти объекты необходимо прочитать.
- [Предложение] Антипарадигмальный дизайн: избыточные копии полей, для которых часто требуются запросы на объединение, помещаются в другие таблицы. Например, атрибут user_name является избыточным в user_account, user_login_log и других таблицах, что снижает количество запросов на соединение.
- [Обязательно] Промежуточная таблица используется для хранения промежуточного набора результатов, и имя должно начинаться с tmp_. Резервная таблица используется для резервного копирования или создания моментального снимка исходной таблицы, и ее имя должно начинаться с bak_. Промежуточные и резервные таблицы регулярно очищаются.
- [Обязательно] Для больших таблиц с количеством строк более 100 Вт таблица изменений должна быть проверена администратором базы данных и выполнена в периоды низкой деловой активности. потому что изменить Таблица создаст блокировку таблицы и заблокирует все записи в таблицу в течение этого периода, что может оказать большое влияние на бизнес.
2.1.3 Оптимизация типа данных столбца
- [Рекомендация] Для столбца автоинкремента (атрибут auto_increment) в таблице рекомендуется использовать тип bigint. Поскольку диапазон хранения unsigned int равен -2147483648~2147483647 (около 2,1 миллиарда), после переполнения будет сообщено об ошибке.
- [Рекомендация] Рекомендуется использовать tinytint или smallint для таких полей, как статус и тип, с небольшой избирательностью в бизнесе, чтобы сэкономить место для хранения.
- [Рекомендация] Рекомендуется использовать тип int для поля IP-адреса в сервисе, а char(15) не рекомендуется. Поскольку int занимает всего 4 байта, вы можете использовать следующие функции для преобразования друг друга, а char(15) занимает как минимум 15 байт. Как только количество строк данных таблицы достигнет 100 миллионов, потребуется дополнительное пространство для хранения 1,1 ГБ. SQL: выберите inet_aton('192.168.2.12'), выберите inet_ntoa(3232236044); PHP: ip2long('192.168.2.12');long2ip(3530427185);
- [Рекомендация] Не рекомендуется использовать enum и set. Поскольку они занимают место впустую, а значения перечисления жестко закодированы, менять их неудобно. Рекомендуется использовать Tinyint или smallint.
- [Рекомендация] Не рекомендуется использовать такие типы, как blob и text. Все они занимают место на жестком диске и в памяти. При загрузке табличных данных в память считываются большие поля, что приводит к нерациональному использованию памяти и снижению производительности системы. Рекомендуется связаться с PM и RD, действительно ли нужно такое большое поле. В Innodb, когда строка записей превышает 8098 байт, будет выбрано самое длинное поле в записи и 768 байт из него будут помещены на исходную страницу, а остальная часть поля будет помещена на страницу переполнения. К сожалению, в формате компактной строки загружаются как исходная страница, так и страница переполнения.
- [Рекомендация] Поле, в котором хранятся деньги, рекомендуется использовать int, терминал умножает на 100 и делит на 100 для доступа. Поскольку int занимает 4 байта, а double — 8 байтов, пространство тратится впустую.
- [Предложение] Используйте varchar для максимально возможного хранения текстовых данных. Поскольку varchar является хранилищем переменной длины, он экономит больше места, чем char. Уровень сервера MySQL предусматривает, что все тексты в строке могут храниться до 65535 байт, поэтому в наборе символов utf8 может храниться максимум 21844 символа, которые будут автоматически преобразованы в поля среднего текста. И текст может хранить до 21844 символов в наборе символов utf8, средний текст может хранить до 2 ^ 24/3 символов, а длинный текст может хранить до 2 ^ 32 символов. Обычно рекомендуется использовать тип varchar, а количество символов не должно превышать 2700.
- [Предложение] Выберите метку времени в качестве типа времени. Поскольку datetime занимает 8 байтов, timestamp занимает только 4 байта, но диапазон составляет от 1970-01-01 00:00:01 до 2038-01-01 00:00:00. Для более продвинутого подхода используйте int для хранения времени и используйте функции SQL unix_timestamp() и from_unixtime() для преобразования.
2.1.4 Дизайн указателя
- [Force] Инструктивный стол должен быть первичным ключом для ID INT / BIGINT AUTO_INCREMENT, а значение первичного ключа запрещено обновляться.
- [Рекомендация] Имя первичного ключа начинается с «pk_», уникальный ключ начинается с «uk_» или «uq_», а общий индекс начинается с «idx_», все в нижнем регистре, с именем или аббревиатурой таблица/поле в качестве суффикса.
- [Обязательно] Для таблиц механизма хранения InnoDB и MyISAM тип индекса должен быть BTREE; для таблиц MEMORY можно выбрать индексы типа HASH или BTREE по мере необходимости.
- [Обязательно] Длина каждой индексной записи в одном индексе не может превышать 64 КБ.
- [Рекомендация] Количество индексов в одной таблице не может превышать семи.
- [Предложение] При создании индекса рассмотрите возможность создания совместного индекса и поставить поле максимальной степенью дискриминации в верхней части. Например, различие пользователя столбца может быть рассчитано путем выбора COUNT (отличный идентификатор пользователя).
- [Рекомендация] В SQL объединения нескольких таблиц убедитесь, что в столбце соединения управляемой таблицы есть индекс, чтобы эффективность выполнения соединения была максимальной.
- [Рекомендация] При построении таблицы или добавлении индекса убедитесь, что в таблице нет избыточных индексов. Для MySQL, если ключ (a, b) уже существует в таблице, то ключ (a) является избыточным индексом и должен быть удален.
2.1.5 Подбаза данных, подтаблица, таблица разделов
- [Обязательно] Поле раздела (ключ раздела) многораздельной таблицы должно иметь индекс или быть первым столбцом составного индекса.
- [Обязательно] Количество разделов (включая подразделы) в одной таблице разделов не может превышать 1024.
- [Обязательно] RD или администратор баз данных должны указать политики создания и очистки таблицы разделов перед подключением к сети.
- [Обязательно] SQL для доступа к секционированной таблице должен содержать ключ секции.
- [Предлагаемый] один файл раздела не более 2G, общий размер не более 50 г. Общее количество разделов не рекомендуется более 20.
- [Обязательно] Операция изменения таблицы для секционированных таблиц должна выполняться в часы пиковой нагрузки.
- [Обязательно] Если принята стратегия подбиблиотек, количество библиотек не может превышать 1024.
- [Обязательно] Если принята стратегия разделения таблиц, количество таблиц не может превышать 4096.
- [Рекомендация] Одна подтаблица не должна превышать 500 W строк, а размер файла ibd не должен превышать 2 ГБ, чтобы обеспечить лучшее распределение данных.
- [Предложение] Используйте метод по модулю, насколько это возможно, для горизонтальных подтаблиц, и рекомендуется использовать дату для подтаблицы для данных журнала и отчета.
2.1.6 Набор символов
- [Обязательно] Все наборы символов самой базы данных, таблиц и столбцов должны быть согласованными, то есть utf8 или utf8mb4.
- [Обязательно] Набор символов клиентской программы или набор символов в переменной среды должен соответствовать набору символов базы данных и таблицы, а унифицированное значение — utf8.
2.1.7 Предложения по проектированию процедурного DAO
- [Рекомендация] Не используйте модель для нового кода.Рекомендуется использовать метод ручного написания SQL + переменные привязки для передачи параметров. Хотя модель может управлять базой данных объектно-ориентированным способом, ее неправильное использование может легко привести к тому, что сгенерированный SQL будет очень сложным, а производительность принудительного преобразования типов, выполняемого самим уровнем модели, будет низкой, что в конечном итоге приведет к снижение производительности базы данных.
- [Рекомендация] Когда интерфейсная программа подключается к MySQL или Redis, должен быть установлен тайм-аут подключения и механизм повторного подключения при сбое, а также должен быть интервал между сбоем и повторной попыткой.
- [Предложение] В отчете об ошибках клиентской программы попробуйте запросить информацию об ошибке исходной экологии MySQL или redis, что удобно для устранения неполадок.
- [Рекомендация] Для интерфейсных программ с пулами подключений начальное, минимальное и максимальное количество подключений, время ожидания и механизм восстановления подключения должны быть настроены в соответствии с потребностями бизнеса, иначе ресурсы подключения к базе данных будут исчерпаны, что приведет к несчастные случаи.
- [Рекомендация] Таблицы типа журнала или истории со временем становятся все больше и больше, поэтому RD или администратор базы данных должны установить план очистки или архивирования данных таблицы, прежде чем подключаться к сети.
- [Рекомендация] На этапе разработки приложения отдел удаленных рабочих столов должен учитывать и избегать влияния задержки между ведущим и подчиненным в базе данных на бизнес. Старайтесь, чтобы кратковременная задержка (в пределах 20 секунд) подчиненной библиотеки не влияла на бизнес.Рекомендуется принудительно выполнять последовательную транзакцию открытия чтения в главную библиотеку или читать подчиненную библиотеку через некоторое время после обновление.
- [Рекомендация] Когда несколько параллельных бизнес-логик обращаются к одному и тому же фрагменту данных (таблице innodb), на стороне базы данных будут генерироваться блокировки строк или даже таблиц, что приведет к снижению параллелизма. Поэтому рекомендуется обновить класс SQL. на основе первичного ключа в максимально возможной степени.
- [Рекомендация] Порядок блокировки между бизнес-логиками должен быть как можно более последовательным, иначе возникнут взаимоблокировки.
- [Рекомендация] Для строк данных или отдельных столбцов с соотношением чтения и записи более 10:1 в одной таблице можно поместить горячие данные в кеш (такой как mecache или Redis), чтобы ускорить доступ и снизить нагрузку на MySQL.
2.1.8 Пример канонического оператора построения таблицы
Более стандартный оператор построения таблицы:
CREATE TABLE user (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`user_id` bigint(11) NOT NULL COMMENT ‘用户id’
`username` varchar(45) NOT NULL COMMENT '真实姓名',
`email` varchar(30) NOT NULL COMMENT ‘用户邮箱’,
`nickname` varchar(45) NOT NULL COMMENT '昵称',
`avatar` int(11) NOT NULL COMMENT '头像',
`birthday` date NOT NULL COMMENT '生日',
`sex` tinyint(4) DEFAULT '0' COMMENT '性别',
`short_introduce` varchar(150) DEFAULT NULL COMMENT '一句话介绍自己,最多50个汉字',
`user_resume` varchar(300) NOT NULL COMMENT '用户提交的简历存放地址',
`user_register_ip` int NOT NULL COMMENT ‘用户注册时的源ip’,
`create_time` timestamp NOT NULL COMMENT ‘用户记录创建的时间’,
`update_time` timestamp NOT NULL COMMENT ‘用户资料修改的时间’,
`user_review_status` tinyint NOT NULL COMMENT ‘用户资料审核状态,1为通过,2为审核中,3为未通过,4为还未提交审核’,
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_id` (`user_id`),
KEY `idx_username`(`username`),
KEY `idx_create_time`(`create_time`,`user_review_status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='网站用户基本信息';
2.2 Написание SQL
2.2.1 Операторы DML
- [Обязательно] В операторе SELECT должно быть указано конкретное имя поля, запрещено писать *. потому что выберите *Данные, которые не должны считываться, также будут считываться из MySQL, вызывая нагрузку на сетевую карту. И как только поля таблицы обновятся, а слой модели не успел обновиться, система сообщит об ошибке.
- [Обязательно] Оператор вставки указывает конкретное имя поля, не записывайте его как вставку в значения t1 (…), причина та же, что и выше.
- 【Предложение】вставить в… значения (XX), (XX), (XX)…. Значение XX здесь не должно превышать 5000. Слишком большое количество значений вызовет задержку синхронизации master-slave, хотя онлайн-линия очень быстрая.
- [Рекомендация] Не используйте UNION в операторе SELECT.Рекомендуется использовать UNION ALL, а количество предложений UNION ограничено пятью. Поскольку union all не нуждается в дедупликации, это экономит ресурсы базы данных и повышает производительность.
- [Рекомендация] Список in значений ограничен 500. Например, выберите… где userid в (….500 или меньше…), это должно уменьшить базовое сканирование, уменьшить нагрузку на базу данных и ускорить запрос.
- [Рекомендация] Пакетное обновление данных в транзакциях требует контроля над числом, выполняет необходимый SLEEP и делает небольшое количество несколько раз.
- [Обязательно] Таблица, участвующая в транзакции, должна быть всеми таблицами INNODB. В противном случае, как только он выйдет из строя, все не будет откатываться, и легко вызвать синхронизацию ведущего и подчиненного терминала.
- [Обязательно] Записи и транзакции отправляются в основную базу данных, а SQL только для чтения отправляется в подчиненную базу данных.
- [Обязательно] За исключением статических таблиц или небольших таблиц (в пределах 100 строк), операторы DML должны иметь условия where и использовать индексы для поиска.
- [Обязательно] Подсказки, такие как sql_no_cache, принудительный индекс, ключ игнорирования, прямое соединение и т. д., запрещены в производственной среде. Поскольку подсказка используется для принудительного выполнения SQL в соответствии с определенным планом выполнения, но по мере изменения объема данных мы не можем гарантировать, что наш первоначальный прогноз верен, поэтому мы должны доверять оптимизатору MySQL!
- [Обязательно] Типы полей слева и справа от знака равенства в условии where должны быть одинаковыми, иначе нельзя будет использовать индекс.
- [Предложение] SELECT|UPDATE|DELETE|REPLACE должно иметь предложение WHERE, а условия предложения WHERE должны быть найдены с использованием индекса.
- [Обязательно] Полное сканирование больших таблиц настоятельно не рекомендуется в рабочих базах данных, но полное сканирование доступно для статических таблиц, содержащих менее 100 строк. Объем данных запроса не должен превышать 25% от количества строк таблицы, иначе индекс использоваться не будет.
- [Принудительно], где пункт, запрещающий использование только полноподобных условий нечеткую функцию поиска, у вас должен быть диапазон другого эквивалента или запроса или не может использовать индекс.
- [Рекомендация] Не используйте функции или выражения для столбцов индекса, иначе индекс нельзя будет использовать. Например, где длина (имя) = «Администратор» или где user_id+2=10023.
- [Предложение] Сократите использование оператора or, оптимизируйте оператор or в объединение, а затем создайте индекс для каждого условия where. например, где a=1 или b=2 оптимизировано так, чтобы где a=1… союз …где b=2, ключ (a), ключ (b).
- [Предложение] Пейджинговый запрос, когда начальная точка ограничения высока, вы можете использовать условие фильтра для фильтрации в первую очередь. Например, выберите a,b,c из предела t1 10000,20; оптимизируется следующим образом: выберите a,b,c из t1, где id>10000 ограничение 20;.
2.2.2 Объединение нескольких таблиц
- [Обязательно] Операторы соединения между базами данных запрещены. Потому что это может уменьшить связь между модулями и заложить прочную основу для разделения базы данных.
- [Обязательно] Запрещено использовать объединение в SQL-операторах бизнес-обновления, таких как update t1 join t2….
- [Рекомендация] Не рекомендуется использовать подзапросы, рекомендуется разделить SQL подзапроса и объединить программу для нескольких запросов или использовать объединение вместо подзапросов.
- [Рекомендация] В онлайн-среде объединение нескольких таблиц не должно превышать 3 таблиц.
- [Рекомендация] Рекомендуется использовать псевдонимы для запросов на объединение нескольких таблиц, а псевдонимы следует использовать для ссылки на поля в списке SELECT, формате database.table, например, выберите a из db1.table1 alias1, где ….
- [Рекомендация] При объединении нескольких таблиц попробуйте выбрать таблицу с меньшим набором результатов в качестве управляющей таблицы для объединения других таблиц.
2.2.3 Транзакции
- [Рекомендация] Количество строк, обрабатываемых оператором INSERT|UPDATE|DELETE|REPLACE в транзакции, контролируется в пределах 2000, а количество параметров, передаваемых в списке IN в предложении WHERE, контролируется в пределах 500.
- [Рекомендация] При работе с данными в пакетах необходимо контролировать интервал обработки транзакций и выполнять необходимый сон, обычно рекомендуемое значение 5-10 секунд.
- [Рекомендация] Для работы вставки таблицы с помощью поля атрибута AUTO_INCREMENT параллелизм должен контролироваться в пределах 200.
- [Обязательно] Программирование должно учитывать влияние «Уровня изоляции транзакций базы данных», включая грязное чтение, неповторяемое чтение и иллюзию. Предлагаемый онлайн уровень изоляции транзакций — REPEATABLE-Read.
- [Рекомендация] Транзакция содержит не более 5 SQL-запросов (кроме платежных услуг). Потому что длинная транзакция приведет к длительной блокировке данных, внутреннему кешу MySQL, чрезмерному потреблению соединений и другим лавинным проблемам.
- [Предложение] Оператор обновления в транзакции должен основываться на первичном ключе или уникальном ключе, насколько это возможно, например, обновление... где id=XX; В противном случае будет сгенерирована гэп-блокировка, и диапазон блокировки будет расширен внутри, что приведет к снижению производительности системы и тупиковой ситуации.
- [Рекомендация] Попробуйте убрать из транзакции некоторые типичные внешние вызовы, такие как вызов веб-сервиса, доступ к хранилищу файлов и т. д., чтобы транзакция не была слишком длинной.
- [Рекомендация] Для некоторых операторов, которые строго чувствительны к задержке master-slave MySQL, включите транзакцию, чтобы принудительно получить доступ к базе данных master.
2.2.4 Сортировка и группировка
- [Предложение] Уменьшить использование порядка и общаться с бизнесом без сортировки или поставить сортировку на стороне программы, чтобы сделать это. порядок, группа Заявления, такие как и отдельные, являются более процессорами, и ресурсы процессора базы данных чрезвычайно драгоцены.
- [Рекомендации] упорядочивать, группировать, различать, в полной мере использовать эти индексы SQL, напрямую извлекая отсортированные данные. Например, где а = 1 Вы можете заказать, используя ключ (a, b).
- 【Предложение】Включить заказ по, группе Для операторов запроса by и Different набор результатов, отфильтрованный по условию where, должен содержаться в пределах 1000 строк, иначе SQL будет очень медленным.
- 2.2.5 Онлайн-выражения SQL [высокий риск] Отключить обновление|удалить t1 … где a=XX limit XX Этот тип оператора обновления с ограничением отключен. Потому что это приведет к несогласованности ведущий-ведомый, что приведет к путанице данных. Рекомендуется добавлять заказ по ПК.
- [Высокий риск] Запретить использование коррелированных подзапросов, таких как обновление t1 set … где имя в (выберите имя из пользовательского где...); крайне неэффективно.
- [Обязательно] Отключите процедуры, функции, триггеры, представления, события и ограничения внешнего ключа. Поскольку они потребляют ресурсы базы данных, снижают масштабируемость экземпляра базы данных. Рекомендации реализованы на стороне программы.
- [Обязательно] Отключите вставку в ... при обновлении дублирующегося ключа... В среде с высоким уровнем параллелизма это приведет к несогласованности между ведущим и подчиненным.
- [Обязательно] запрещено присоединиться к отчете об обновлении таблиц, таких как обновление T1, T2, где T1.ID = T2.ID ....