【问题标题】:MYSQL innodb with almost max number of varchar columns (60K)具有几乎最大数量的 varchar 列(60K)的 MYSQL innodb
【发布时间】:2010-12-28 20:44:22
【问题描述】:

我正在构建一个数据库,它要求每行大约 60,000 字节(非常接近 mysql 最大行大小,基本上有很多 varchar(500) 语句 [必要])。现在,据我所知,这在我的主义中是可以的。

但是,由于它的行锁定行为,我正在考虑使用 innodb(我的表有很多更新)。我刚刚遇到了一些关于 innodb 不喜欢大行(最大大约 8000 字节或其他东西)的令人不安的信息。

所以,鉴于我的表将有大约 60,000(!)字节的行,这对 innodb 来说是个问题吗?这是一个大问题吗?交易破坏者?你有什么建议?

表: ID (int, autoinc, primary key), varchar(500), varchar(500)...repeat...varchar(500) 直到到达表末尾

【问题讨论】:

  • 请解释一下你的行的构成。例如,Blob 和 Text 列的大小判断规则略有不同。
  • 我添加了我的行的解释。总计约 700 万行。
  • 我建议不要使用 MySQL。您是否有任何理由要为此使用 MySQL 而不是某些 NoSQL 解决方案?
  • 为什么你需要 120 个 varchar(500) 列 - 也许你应该插入行来代替!!
  • 为什么是mysql? - 数据库将在共享主机上,它们拥有的一切......为什么是 120 个 varchars?因为那是最快的方法!我考虑过连接,但这太慢了,这应该很快,因为行是索引的。速度是最重要的,可用大小很大,带宽也很大。我需要它快。 V.fast.

标签: mysql


【解决方案1】:

不知道你为什么选择使用 120 varchar(500) 列,但我认为你最好插入行 - 像这样:

drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varbinary(32) unique not null,
next_note_id smallint unsigned not null default 0
)
engine=innodb;

drop table if exists user_notes;
create table user_notes
(
user_id int unsigned not null,
note_id smallint unsigned not null,
note varchar(512) not null,
primary key (user_id, note_id) -- clustered composite PK
)
engine=innodb;

delimiter #

create trigger user_notes_before_ins_trig before insert on user_notes
for each row
begin
declare v_id int unsigned default 0;

  select next_note_id + 1 into v_id from users where user_id = new.user_id;
  set new.note_id = v_id;
  update users set next_note_id = v_id where user_id = new.user_id;
end#

delimiter ;

insert into users (username) values ('f00'),('bar');

insert into user_notes (user_id, note) values
(1,'user 1 note 1'), (1,'user 1 note 2'), (1,'user 1 note 3'),
(2,'user 2 note 1');

select * from users;
user_id username   next_note_id
======= ========   ============
1         f00        3
2         bar        1

select * from user_notes;
user_id note_id note
======= ======= ====
1         1       user 1 note 1
1         2       user 1 note 2
1         3       user 1 note 3
2         1       user 2 note 1

希望对你有帮助:)

【讨论】:

  • 有趣,但已经有 700 万行,如果每个 100 个 varchars,这是否意味着 7 亿行?>
  • 在我的示例中,如果每个用户有 100 条笔记并且有 700 万用户,那么您将拥有 (700 万用户 * 100 条笔记) = 7 亿行数据。如果您对此感到担心,您可能想在这里查看我的答案stackoverflow.com/questions/4419499/…(只需将论坛视为用户,将线程视为注释 - 5 亿行,负载下的查询运行时间为 0.02 秒)跨度>
【解决方案2】:

InnoDB 对行大小有相同的 64K 限制。它还将行大小限制为页面大小的一半,但这不包括 varbinary、varchar、blob 或 text 列。默认情况下,InnoDB 的页面大小为 16K,因此您最终会得到 8K 的限制。但是您应该可以进行转换,因为您的列是 varchar。

但是,如果您不使用 InnoDB 插件,则使用的行存储格式(“compact”)可能效率低下,因为超过 768 字节的 varchar 内容存储在补充的 16K 页中,而这 4 个额外的页在您的案例 (ceil(60/16)) 可能存储在 InnoDB 池中的任何位置(如果您的数据集适合 InnoDB 缓冲池,则不是问题)。我会使用 InnoDB 插件的 Dynamic row 格式。

请注意,大型表的转换需要很长时间。尝试先在您的开发机器上转换备份。

【讨论】:

  • "超过 768 字节的 varchar 内容存储在补充的 16K 页中" 这很有趣。每个 varchar 将是 latin1,我相信每个字母存储为 1 个字节。因此, varchar(500) 可以吗?每个 varchar 或行中所有 varchar 的 768 个限制是否加在一起?欢呼
  • 768 字节的行内存储限制适用于所有 v/v/b/t 列。因此,如果您总共有超过 768 个字节,InnoDB 将使用额外的页面来存储超过 768 个字节的内容(使用旧的“紧凑”格式)。如果使用新的动态行格式,所有的 v/v/b/t 列都存储在额外的页面中,因为它使 b-tree 索引的大小更小,从而加快了索引操作(CPU 的内存分页更少)。从 MySQL 5.0.3 开始,单个 varchar 的最大长度为 65,535 字节。 dev.mysql.com/doc/refman/5.0/en/char.html
  • 您对所有 c/b/t 列 TOGETHER 的确定程度如何?我原以为这是每个人的,8000 是一切的绝对最大值。 768 似乎太低了......
  • 阅读我在答案中发布的两个链接;那里有解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多