Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 设计数据库以存储列表_Mysql_List_Database Design - Fatal编程技术网

Mysql 设计数据库以存储列表

Mysql 设计数据库以存储列表,mysql,list,database-design,Mysql,List,Database Design,我为列和表名的模糊性道歉。 我的数据库有两个表A和B。这些表之间存在多对多关系 表A约有200条记录 Table A structure Id. Definition 12 Def1 42 Def2 .... etc. 表B有大约50亿条记录 Column 1 . Associated Id(from table A) eg . abc 12 abc 21 pqr 42 我试图优化表B中存储数据的方式,因为它有很多冗余数

我为列和表名的模糊性道歉。 我的数据库有两个表A和B。这些表之间存在多对多关系

表A约有200条记录

Table A structure
Id.   Definition
12    Def1
42    Def2 .... etc. 
表B有大约50亿条记录

Column 1 .   Associated Id(from table A)
eg . abc      12
     abc      21
     pqr      42
我试图优化表B中存储数据的方式,因为它有很多冗余数据。我想到的结构如下

Column 1        Associated Ids
abc             12, 21
pqr             42
将新行添加到表A时,“关联Id”列可以有更新

在这个场景中,这是一个好的结构吗?如果是,“关联Id”的列类型应该是什么?我正在使用mysql数据库

创建表语句

CREATE TABLE `A` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(100) DEFAULT NULL,
  `name` varchar(100) DEFAULT NULL,
  `creat_usr_id` varchar(20) NOT NULL,
  `creat_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `modfd_usr_id` varchar(20) DEFAULT NULL,
  `modfd_ts` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `A_ak1` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=277 DEFAULT CHARSET=utf8;

CREATE TABLE `B`(
  `col1` varchar(128) NOT NULL,
  `id` int(11) NOT NULL,
  `added_dt` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `creat_usr_id` varchar(20) NOT NULL,
  `creat_ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`col1`,`id`,`added_dt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!50100 PARTITION BY RANGE (UNIX_TIMESTAMP(added_dt))
(PARTITION Lessthan_2016 VALUES LESS THAN (1451606400) ENGINE = InnoDB,
 PARTITION L`Ω`essthan_201603 VALUES LESS THAN (1456790400) ENGINE = InnoDB,
 PARTITION Lessthan_201605 VALUES LESS THAN (1462060800) ENGINE = InnoDB,
 PARTITION Lessthan_201607 VALUES LESS THAN (1467331200) ENGINE = InnoDB,
 PARTITION Lessthan_201609 VALUES LESS THAN (1472688000) ENGINE = InnoDB,
 PARTITION Lessthan_201611 VALUES LESS THAN (1477958400) ENGINE = InnoDB,
 PARTITION Lessthan_201701 VALUES LESS THAN (1483228800) ENGINE = InnoDB,
 PARTITION pfuture VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */;
索引

  Table Non_unique  Key_name    Seq_in_index    Column_name Collation   Cardinality Sub_part    Packed  Index_type  Comment Index_comment
    B          0        PRIMARY         1             col1        A        
 2             NULL       NULL      BTREE       
    B          0        PRIMARY         2              id         A        
 6             NULL       NULL      BTREE       
    B          0         PRIMARY        3             added_dt    A        
 6             NULL       NULL      BTREE       

这里有50亿行。让我来回顾一下:

  • col1
    varchar(128)不为空
这个专栏多长时间重复一次?就是,值得"正常化"吗?

  • id
    int(11)不为空
将此列的大小减半(4字节->2),因为您只有200个不同的ID:

a_id SMALLINT UNSIGNED NOT NULL
值的范围:0..65535

  • added_dt
    timestamp NOT NULL默认当前_时间戳
请解释为什么这是PK的一部分。这是一件很奇怪的事

  • create_usr_id
    varchar(20)不为空
  • 创建时间戳
    时间戳不为空默认当前时间戳
把它们当作乱七八糟的东西扔掉,除非你能证明用这种方式跟踪50亿个行动是合理的

  • 主键(
    col1
    id
    已添加)
我敢打赌你最终会在同一秒钟内得到两行。PK是“唯一的”。也许你只需要
(col
,一个id)`?否则,您将允许多次添加col-a_id对。或者您希望IODKU添加新行,而不是更新时间戳

  • 分区
如果(可能仅当)您打算删除“旧”行,这将非常有用。否则请解释为什么选择分区

如果不查看主
选项
,就很难查看架构。对于大型表,我们还应该检查
插入
更新
、和
删除
,因为它们都可能带来严重的性能问题


以每秒插入100行的速度,增加50亿行需要一年多的时间。排得多快?这可能也是一个重要的性能问题。

“在这种情况下创建这种结构好吗?”不好。对于几乎所有可能的情况,这种结构都不好。将您的表和索引定义(
create table…
create index…
)粘贴到您的问题中。在这个问题上附议“否”。将多个值塞进一个字段几乎从来都不是一个好主意。我添加了create表和索引。什么是更好的解决方案?因为每个col1值都有多个记录。我正在尝试将此值减少到每列一行。您尝试优化的目的是什么?获取特定id的所有col1值?这里的多余部分是什么?B列是否总是相同的?如果是这样的话——为什么他们在B?@Uuerdo——我同意,但我要指出的是,在少数情况下,commalist能够令人满意,甚至更快。如果OP将
连接到另一个表,那么commalist是一个非常糟糕的主意(如您所说)。大家好,非常感谢您的所有回答,非常抱歉出现MIA。@Gabi Lee-col1有冗余数据。可能有大约500万行不同的行。在我之前的DBA创建了这个表,其中col1链接到的每个Id都有一行。所以我最终得到了500万*257行。我们在这些表上执行的联接不多。@uuerdo这也是我所在组织的一位高级DBA建议的。但我在互联网上发现的例子很少:(@Codegak-应该有助于规范化
col1
,用
INT UNSIGNED
MEDIUMINT UNSIGNED
替换它)。