MySQL大表管理?

时间:2011-09-14 21:43:51

标签: php mysql size implementation

我需要进行此实施:

enter image description here

我正在使用Php和MySQL。如您所见,价格可以动态构建。为了管理这个要求,我做了以下架构:

`tbl_states` (id, state)
`tbl_prices` (id, price)
`tbl_years`  (id, year)
`tbl_states_prices` (id, state_id, customer_id, year_id, price_id, value)

每个价格的值将存储在tbl_states_prices中。价值取决于州,客户和年份。我关注的是这张桌子的大小,因为最大年数是20,价格大约是6,平均客户数是300.

我不知道使用此架构会产生什么后果。我该如何管理这张桌子?按客户分成小表?看法?我缺乏数据库经验对我没有帮助。建议将不胜感激。

3 个答案:

答案 0 :(得分:1)

你提供的信息很少,所以我不得不猜测一个场景 就我自己而言,这是一个可能的。

我们为零售商保留信息。每个零售商都有很多客户,还有一个 客户可能是许多零售商的客户,所以这可能是多对多的 关系,这需要另一张桌子来帮助。

对于每对cutomer和零售商,我们保留独特的费用(预测)。 一笔费用只属于一个客户。

Year1,year2字段no,year必须是单个字段,字段不多。和 因为这是一个多次出现的场地(类似于电话机箱) 良好的做法需要另一张桌子来帮助我们。所以没有这样的事情 动态领域,领域像石头一样静止,是一个基本规则!另外如果 我们正在讨论真正庞大的数据(我认为不是这样,我们可以 例如,打破与特定年份相关的部分的费用表,但这样 需要更多的工作) 一件非常重要的事情......你可能会想到一个特定的方式 水平,垂直地呈现这些数据,第1年,第2年等。但是你永远不会 让这个想法干扰你的关系图,视觉显示(可能随时改变) 和设计必须分开。

至于州,有一个小技巧可以让场地变小,这意味着更快的工作 并省略状态表。它需要一个简单的PHP函数,当给定一个状态 例如,加利福尼亚州存储了一个tinyint而不是varchar California。或者你可以保持一个 状态表,其tinyint id作为外键传递给charge表。 选择你喜欢的。

/ 实体是零售商和客户的概括。概括 需要处理类似的字段,例如零售商和客户 有电子邮件,地址等。另一方面,客户和零售商都是 我们需要它来处理不同字段的实体规范 例如,我们不关心退休人员是否结婚了! /

以下只是一个指导性示例。

drop table if exists `Entity_Phone`;
drop table if exists `Retailer_Customer`;
drop table if exists `Charge`;
drop table if exists `Retailer`;
drop table if exists `Customer`;

drop table if exists `Entity`;
  CREATE TABLE `Entity` (
  `entity_id` INT UNSIGNED NOT NULL   AUTO_INCREMENT,
  /*example code 0 is for retailer and code 1 is for customer*/
  `entity_code` tinyint not null,
  `entity_other_field` VARCHAR(30) NOT NULL,
  PRIMARY KEY  (`entity_id`)
) ENGINE=InnoDB   DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
/*You don't have to use utf8 if not needed*/

/*Phone number, instead of only phone you can store more info
like multiple emails etc, just change the table name to  make sense,
the datatype and in the php function that associates codes add 
as many codes needed*/
CREATE TABLE `Entity_Phone` (
  `entity_id` INT UNSIGNED NOT NULL  ,
  `phone` BIGINT UNSIGNED NOT NULL  ,
  /*code 1 is for fix phone, 2 is for mobile phone and 3 for fax*/
  `identification_code`  TINYINT UNSIGNED DEFAULT '1' NOT NULL,
  PRIMARY KEY  (`entity_id`),
  CONSTRAINT `fk1EntData` FOREIGN KEY (`entity_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE
) ENGINE=InnoDB ROW_FORMAT=COMPACT;


  CREATE TABLE `Retailer` ( 
  `retailer_fname` VARCHAR(30) NOT NULL,
  `retailer_lname` VARCHAR(30) NOT NULL,
  /*pkey directly shared from entity table, just with a different name*/
  `retailer_id` INT UNSIGNED NOT NULL ,
  PRIMARY KEY  (`retailer_id`),
  CONSTRAINT `fk1RetEnt` FOREIGN KEY (`retailer_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE
) ENGINE=InnoDB   DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

  CREATE TABLE `Customer` ( 
  `customer_fname` VARCHAR(30) NOT NULL,
  `children_number` tinyint not null,
   `customer_id` INT UNSIGNED NOT NULL ,
  PRIMARY KEY  (`customer_id`),
   CONSTRAINT `fk1CustData` FOREIGN KEY (`customer_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE
) ENGINE=InnoDB   DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;



CREATE TABLE `Retailer_Customer` ( 
  `customer_id` INT UNSIGNED NOT NULL  ,
  `retailer_id` INT UNSIGNED NOT NULL  ,   
  PRIMARY KEY  (`customer_id`,`retailer_id`),
  CONSTRAINT `fk1RetCust` FOREIGN KEY (`customer_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE, 
 CONSTRAINT `fk2RetCust` FOREIGN KEY (`retailer_id`)
        REFERENCES `Entity` (`entity_id`)
        ON DELETE CASCADE

) ENGINE=InnoDB ROW_FORMAT=COMPACT;




/*
if you want to keep the state table... for example you might need to store 
information for states so you need this table to keep those fields
CREATE TABLE `State` (
  `state_id` tinyINT UNSIGNED NOT NULL  ,
  `state_name` varchar(50) not null ,  
  PRIMARY KEY  (`state_id`),
  unique(`state_name`) 
) ENGINE=InnoDB ROW_FORMAT=COMPACT;
*/
CREATE TABLE `Charge` ( 
  `retailer_id` INT UNSIGNED NOT NULL  ,
   `customer_id` INT UNSIGNED NOT NULL  ,
  `state_code` TINYINT UNSIGNED NOT NULL  ,
  /*state  could be stored here directly as 
  varchar however this way it asks less space,
  is faster and allows no orthographical erros 
 on insertion */
  /*`state_id` tinyint UNSIGNED NOT NULL  , if you want the state table*/
    `charge_date_time`  DATETIME  NOT NULL,
  index(`customer_id`),
  PRIMARY KEY  (`retailer_id`,`customer_id`,`charge_date_time`),
  CONSTRAINT `fk1Charge` FOREIGN KEY (`retailer_id`)
        REFERENCES `Retailer` (`retailer_id`)
        ON DELETE CASCADE,
  CONSTRAINT `fk2Charge` FOREIGN KEY (`customer_id`)
        REFERENCES `Customer` (`customer_id`)
        ON DELETE CASCADE 
 /* if you want the state table
 ,CONSTRAINT `fk2pr` FOREIGN KEY (`state_id`)
        REFERENCES `State` (`state_id`)
        ON DELETE CASCADE
*/
) ENGINE=InnoDB ROW_FORMAT=COMPACT;



/*This is how you insert a Retailer*/  
insert into `Entity` (`entity_code`, `entity_other_field`)
  values ('0','test');
insert into `Retailer` (`retailer_fname`, `retailer_lname`,
  `retailer_id`) values ('John', 'Smith',(SELECT LAST_INSERT_ID()));
insert into `Entity_Phone` (`entity_id`, `phone`,`identification_code`) values 
((SELECT LAST_INSERT_ID()), 123222,3);
/****************************************************/


/*This is how you insert a Customer*/ 
insert into `Entity` (`entity_code`, `entity_other_field`)
  values ('1','test');
insert into `Customer` (`customer_fname`, `children_number`,
  `customer_id`) values ('Jimm', 3,(SELECT LAST_INSERT_ID()));
insert into `Entity_Phone` (`entity_id`, `phone`,`identification_code`) values 
((SELECT LAST_INSERT_ID()), 43543,3);
/****************************************************/




/*This is how you insert a charge*/
insert into `Charge` (`retailer_id`, `customer_id`,`state_code`,
`charge_date_time`)
  values ((select `retailer_id` from `Retailer` where `retailer_fname`='John'),
  (select   `customer_id` from `Customer` where `customer_fname`='Jimm'),34,(now()));

  /*This is how you retrieve a charge*/
  select * from `Charge` where year(`charge_date_time`) ='2011'

答案 1 :(得分:0)

如果您需要建议,我建议您在桌子上使用MyISAM引擎,因为选择速度很快。我在具有+1百万行的表上使用InnoDB,因为我需要使用外键约束,所以对mysql没有任何意义。

答案 2 :(得分:0)

  1. 步骤1 =需求分析(与具有相关知识的人进行分析讨论) 你识别实体(简单地说,名词通常是实体:人,客户,供应商等,动词通常是关系:工作,购买,供应等) 那么实体的价格(对此有疑问),是零售商(我打赌这个)等等。零售商可能是一个实体,因为它可以独立存在,而电话号码不能独立存在,电话号码是没有意义的,除非相关对一个人!客户可以独立存在,这是有道理的!

  2. 另一件事(在许多其他人中)是问你自己,我要问数据库,

    • 我会询问与州仅相关的价格,还是仅与州和年相关的价格
  3. 我必须在这里停止理论因为它太大了,而且因为理论没有多大帮助我会做一些非常实际的通知:

    <强>声明

    请记住,我不知道需求分析,因此我可能在某处完全错误

    • 有一个代表一个实体的主表(这些表是那些没有外键的表)关于价格(你定义它的方式)可能是一个不好的做法,它可能会伤害你的工作在某个地方。这意味着不一致,设计不好,无效设置等是可以容忍的,不一致的是。价格和价值......我很确定没有像价值这样的东西,只有价格!因此,如果我们正在讨论数据库表,那么设计说价格1,价格2等等我不相信。

      • 多年来一张桌子,没办法!年份是一个字段,是实体的属性,而不是实体!

      • 状态,你是什么意思,像纽约等,有时候它是一个领域。

    • 设计良好的表具有简单的主键(例如客户ID)或复合键(例如学生ID和课程ID)。在 tbl_states_prices 中,第一个字段包含一个id,我很漂亮这个id不仅没用,而且还有误导性,可能有害。也许你这样做是因为一些外键可能是空的,这意味着设计不好。

    一个梦幻般的系统要求和设计可能是这样的:

    1. 我们保留有关零售商的信息,因此零售商是一个实体,其名称,位置,网站,州(纽约),电话(通常存储在第二个表中的原因是多个出现的值)等字段。从您的屏幕截图因此,您将零售商称为客户。
    2. tbl_retailer(retail_id,姓名,姓氏等)

      1. 然后你有一个带有复合主键的(使用外键)表。现在你必须决定日期的详细程度。你不能谈论一年如果一年有很多价格,你必须谈论一个月,几周甚至几个小时,这一切都取决于价格变化的频率。
      2. tbl_prices(retail_id,statedatetime

        所有字段都构成复合主键!您不可能以这种方式记录不一致的记录。在你的设计中,我可以输入相同的价格,同一个客户,相同的状态一百万次,唯一的区别是无意义的id(tbl_states_prices的第一个字段)。这就像插入一百万次 1.约翰史密斯父亲已婚等 2.约翰史密斯父亲已婚等 .... 1000000.约翰史密斯父亲已婚等

        这是多么一致,有效等等?!

        我删除了这件衣服的一小部分,它在新的衣服中被覆盖和改进。