MySQL - 关于某些表的正确方式和性能

时间:2017-08-05 18:11:45

标签: mysql sql performance

我对更好的方法感到有点困惑,我有这些表:

国家

CREATE TABLE `country` (
  `country_id` int(11) NOT NULL auto_increment,
  `country_name` varchar(2) NOT NULL,
  PRIMARY KEY  (`estado_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

状态

CREATE TABLE `state` (
  `state_id` int(11) NOT NULL auto_increment,
  `state_name` varchar(100) NOT NULL,
  `country_id` int(11) NOT NULL,
  PRIMARY KEY  (`state_id`),
  KEY `tc001_ix` (`county_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

ALTER TABLE `state`
  ADD CONSTRAINT `tc001_ix` FOREIGN KEY (`county_id`) REFERENCES `county` (`county_id`) ON DELETE CASCADE ON UPDATE CASCADE;

城市

CREATE TABLE `city` (
  `city_id` int(11) NOT NULL auto_increment,
  `city_name` varchar(100) NOT NULL,
  `state_id` int(11) NOT NULL,
  PRIMARY KEY  (`city_id`),
  KEY `tc002_ix` (`state_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

ALTER TABLE `city`
  ADD CONSTRAINT `tc002_ix` FOREIGN KEY (`state_id`) REFERENCES `state` (`state_id`) ON DELETE CASCADE ON UPDATE CASCADE;

位置

CREATE TABLE `location` (
  `location_id` int(11) NOT NULL auto_increment,
  `location_field01` varchar(50) NOT NULL,
  `location_field02` varchar(50) NOT NULL,
  `city_id` int(11) NOT NULL,
  PRIMARY KEY  (`location_id`),
  KEY `ta001_ix` (`city_id`)
) ENGINE=InnoDB  DEFAULT charset utf8;

ALTER TABLE `tb_location`
  ADD CONSTRAINT `ta001_ix` FOREIGN KEY (`city_id`) REFERENCES `city` (`city_id`) ON DELETE CASCADE ON UPDATE CASCADE;

当我按State运行Location表的查询时,我应该在Location表或查询中放置一个外键country_id我应该在Cities表中进行内部联接然后是State表吗?我也会有过滤器,可以过滤城市。

我想现在正确的方法和更好的表现是什么:

  • 1个外键 city_id
  • 2个外键 city_idstate_id

感谢。

2 个答案:

答案 0 :(得分:1)

首先,您应首先进行标准化数据库设计,而不存储重复数据。

如你所知,它说:

  

每个国家都有自己的国家。每个州都有自己的城市。每个城市都有   它的地点。

这种类型的关系在UML语言中称为Composition。使用此设计您不能在城市之外或没有州的国家/地区,这是您应该问的主要问题:是否可以,这就是我想要的?

如果将State_Id添加到Location表,则会对数据库进行反规范化。只有在您遇到大型性能问题或类似问题时,才建议这样做。

City_ID = NULLState_Id = XXX的位置可能意味着任何城市之外的位置,但当您所有的地点都在城市内时,则无需将State_ID添加到Location } table。

因此,您不应该将State_ID添加到Locations表。 不要在没有很强烈理由的情况下复制数据并且不对数据库进行反规范化。使用JOIN和其他SQL命令来获取与数据相关的表格。

如果您不确定如何构建表,则应该绘制类或数据库图。

enter image description here

答案 1 :(得分:0)

您的位置表的目的是什么?我认为最好的方法是使用INNER JOIN(带城市的州)。从逻辑上讲,一个城市属于一个州(无论一个城市是否在另一个州重复)。您的City表可能有一个指向State表的FK。然后,你只需要一个FK。

顺便说一句,检查你的脚本(你写了#34; county"而不是" country")。

以下脚本与您的相似,但在MSSQL中没有Country表(进行必要的更改):

IF NOT EXISTS(SELECT 1 FROM sys.tables WHERE name = 'States')
CREATE TABLE States(
    IdState     TINYINT IDENTITY(1,1) NOT NULL,
    StateName   VARCHAR(35) NULL,
    CONSTRAINT  PK_States PRIMARY KEY(IdState)
)

IF NOT EXISTS(SELECT 1 FROM sys.tables WHERE name = 'Cities')
CREATE TABLE Cities(
    IdCity      SMALLINT IDENTITY(1, 1) NOT NULL,
    CityName    VARCHAR(100) NULL,
    IdState     TINYINT NULL,
    CONSTRAINT  PK_Cities PRIMARY KEY(IdCity),
    CONSTRAINT  FK_Cities_States FOREIGN KEY(IdState) REFERENCES States(IdState)
)

希望这有帮助!