MySQL查找重复数据
如何查找重复行如何删除重复行如何查找多列上的重复行错误的查询语句几种正确的方法如何查找重复行第一步是定义什么样的行才是重复行。多数情况下很简单:它们某一列具有相同的值。本文采用这一定义,或许你对“重复...
2024.11.151. MySQL Server 层 的限制为单条记录的大小不超过 65535 字节;
2. InnoDB 层 不能超过 innodb_page_size 大小的一半(实际上还要小一点,因为要扣除一些页中元数据信息), 以默认的 16K 设置为例,其限制为 8126。
另:以下计算方式均已 MySQL 5.7.27 进行说明。
二、Server 层限制的计算方法2.1 计算过程
一般说来,如果是 MySQL Server 层做了限制,则返回如下报错:
Row size too large. The maximum row size for the used table type,not counting BLOBs, is 65535.This includes storage overhead, check the manual.You have to change some columns to TEXT or BLOBs所以可以根据这个报错来定位到计算方式,其关键函数路径如下:
mysql_prepare_create_table/* sql/sql_table.cc:3474 */--> mysql_create_frm/* sql/unireg.cc:107 */--> pack_header/* sql/unireg.cc:733 */在 pack_header 中存在这部分代码:
if (reclength > (ulong) file->max_record_length()) /* 右值为 65535 */{my_error(ER_TOO_BIG_ROWSIZE, /* 这个就是上面的报错信息对应的状态值 */MYF(0),static_cast(file->max_record_length()));DBUG_RETURN(1);}重点在于 reclength 的值是否 大于 65535。因此了解一下 reclength 的计算过程:
/* sql/unireg.cc:843 */if (field->offset + data_offset + length > reclength)reclength= field->offset + data_offset + length;/*field->offset 的计算方式sql/sql_table.cc:3816*/while ((sql_field=it++)) { /* 省略部分 */sql_field->offset= record_offset;/* 当前记录的数据偏移量 */if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)auto_increment++;if (sql_field->stored_in_db)record_offset+= sql_field->pack_length; /* 累加当前字段的pack_length */}/*data_offset 的计算方式sql/unireg.cc:139*/data_offset= (create_info->null_bits + 7) / 8;/*length 的计算方式sql/unireg.cc:833*/length=field->pack_length; /* 这个pack_length就是和字段类型相关,以varchar为例*//* sql/sql_table.cc:3082 */sql_field->sql_type=MYSQL_TYPE_VAR_STRING;sql_field->pack_length= calc_pack_length(sql_field->sql_type,(uint) sql_field->length);关于 `calc_pack_length` 的计算方式如下:size_t calc_pack_length(enum_field_types type, size_t length){switch (type) {case MYSQL_TYPE_VAR_STRING:case MYSQL_TYPE_STRING:case MYSQL_TYPE_DECIMAL: return (length);case MYSQL_TYPE_VARCHAR: return (length + (length < 256 ? 1: 2));case MYSQL_TYPE_YEAR:case MYSQL_TYPE_TINY: return 1;case MYSQL_TYPE_SHORT : return 2;case MYSQL_TYPE_INT24:case MYSQL_TYPE_NEWDATE: return 3;case MYSQL_TYPE_TIME: return 3;case MYSQL_TYPE_TIME2:return length > MAX_TIME_WIDTH ?my_time_binary_length(length - MAX_TIME_WIDTH - 1) : 3;case MYSQL_TYPE_TIMESTAMP: return 4;case MYSQL_TYPE_TIMESTAMP2:return length > MAX_DATETIME_WIDTH ?my_timestamp_binary_length(length - MAX_DATETIME_WIDTH - 1) : 4;case MYSQL_TYPE_DATE:case MYSQL_TYPE_LONG: return 4;case MYSQL_TYPE_FLOAT : return sizeof(float);case MYSQL_TYPE_DOUBLE: return sizeof(double);case MYSQL_TYPE_DATETIME: return 8;case MYSQL_TYPE_DATETIME2:return length > MAX_DATETIME_WIDTH ?my_datetime_binary_length(length - MAX_DATETIME_WIDTH - 1) : 5;case MYSQL_TYPE_LONGLONG: return 8;/* Don‘t crash if no longlong */case MYSQL_TYPE_NULL: return 0;case MYSQL_TYPE_TINY_BLOB:return 1+portable_sizeof_char_ptr;case MYSQL_TYPE_BLOB: return 2+portable_sizeof_char_ptr;case MYSQL_TYPE_MEDIUM_BLOB:return 3+portable_sizeof_char_ptr;case MYSQL_TYPE_LONG_BLOB:return 4+portable_sizeof_char_ptr;case MYSQL_TYPE_GEOMETRY: return 4+portable_sizeof_char_ptr;case MYSQL_TYPE_JSON: return 4+portable_sizeof_char_ptr;case MYSQL_TYPE_SET:case MYSQL_TYPE_ENUM:case MYSQL_TYPE_NEWDECIMAL:abort(); return 0;// This shouldn‘t happencase MYSQL_TYPE_BIT: return length / 8;default:return 0;}}2.2 小结
根据上面计算方式的梳理,在 MySQL Server 层计算长度的公式,可以写成这样的伪代码:
data_offset = (number_null_field + 7) / 8; /*number_null_field表示允许为null的字段数*/total_length = 0;for (int i = 0; i < n_fileds; i++) {total_length += calc_pack_length(field_type, length)}/*field_type:数据类型length:数据的字节数注意varchar(100) 的字节数,在utf8mb4环境下,字节数为400*/total_length += data_offset;通过上述计算,需要满足 total_length 8126).Changing some columns to TEXT or BLOB may help.In current row format, BLOB prefix of 0 bytes is stored inline.
通过对报错信息的搜索,其判断方式如下:
/* dict0dict.cc:2515 *//* Check the size limit on leaf pages. */if (rec_max_size >= page_rec_max) {ib::error_or_warn(strict) 40 ? 40 : field.length;}rec_max_size += field_max_size + field_ext_max_size;}通过上述计算,需要满足 rec_max_size < 8126,即可通过 InnoDB 层的检查。
四、总结1. 必须在 MySQL Server 层和 InnoDB 层同时满足上述条件,才能建表成功;2. 如果出现上述报错情况,大部分是因为 varchar 等设置过大,建议可以将一些字段逐步缩小,或者用 text 进行代替;
如何查找重复行如何删除重复行如何查找多列上的重复行错误的查询语句几种正确的方法如何查找重复行第一步是定义什么样的行才是重复行。多数情况下很简单:它们某一列具有相同的值。本文采用这一定义,或许你对“重复...
2024.11.15在MySQL中,可以使用DESC命令和SHOW COLUMNS命令来查看数据表的结构和字段信息。如果想查看每个字段的宽度,可以使用FULL关键字添加到DESC命令中。此外,还可以通过查询INFORMA...
2024.11.15概述今天主要介绍MySQL查看数据库表容量大小的几个方法,仅供参考。1、查看所有数据库容量大小selecttable_schema AS ‘数据库‘,sum( table_rows ) AS ‘记录数...
2024.11.15不要问我为什么要把mysql安装在windows,而不把它装在linux下,哪怕是虚拟机里的linux,我也不知道为什么,今天我要告诉大家的两个字,‘认真’,因为这两认真头疼了我一上午,一上午没搞好,...
2024.11.15MySQL对用户密码强度有比较灵活的设置,可以根据实际系统需要对密码复杂度进行设置,具体步骤与注意事项如下:1、检查是否开启密码复杂度校验:mysql> show variables like ‘%v...
2024.11.15