2013-05-20 31 views
0

我想创建一个表,这个信息:拆分数据到两个表

ID bigint(20) PK AI 
FID bigint(20) unique 
points int(10) index 
birthday date index 
current_city varchar(175) index 
current_country varchar(100) index 
home_city varchar(175) index 
home_country varchar(100) index 
Engine = MyISAM 

在学校学到:创建2个额外的表,一个与城市和一个与国家和FK到表插入数据时。我怀疑的原因是:

此表将有大约10M插入一小时。如果我插入一行,并且每次插入都必须查找城市FK和国家FK,我恐怕会失去很多速度?当我选择仅在WHERE ID = ID时发生的行时,这是否值得我获得的收益?将会有大约25M这些选择一个小时。

+0

感谢您的编辑,因为您看到我对于stackoverflow也很新颖:) –

+0

我会说要这样做。使用外键维护您的完整性并改善查询的好处将超过插入和更新的轻微开销。插入速度非常快,无论如何,我怀疑插入开销的影响是显而易见的。 – Scotch

回答

2

过早的优化,如果所有罪恶的根源。首先设计干净,然后在有实际性能数据时进行优化。

一个干净的设计将是一个正确的标准化表格,即具有独立的城市和一个国家的表。

我怕如果我插入一行,并有查找城市FK和国家FK每次插入,我可能会失去很多的速度?

实际上,varchar列中插入只是小的ID,而不是原国家/城市的名称可能是更有效的:

  • 这将导致更少的磁盘写入
  • 你有的MyISAM表;所以它没有FK的支持,并没有做任何外键查找/检查
  • 与整数更换varchar列将把表fixed-length rows format,这可能比动态长度格式

基准与实际数据/工作量,并查看是否取消正火真的是值得的。

+0

我看到你的观点,我对MySQL和PHP(用于在C#中编程)非常新,非常感谢这些信息。没有FK查找检查当然更不完整,但插入时会更快? –

1

还有就是为什么DB正常化存在的理由。
使用表的城市,一个国家,并通过FK是你的主表加入他们的行列。
另外,你知道哪个国家有100个字符的名字?
你认识哪个城市有175个字符?
ID可以是bigint,但是您确定需要BIGINT(20)吗,INT(11)不会满足吗?无论如何,AUTOINCREMENT它,而不是UNIQUE它,它没有任何意义。
另外,您在每列上都有索引,但没有组合索引。这有很多原因是错误的。不要pre-index,但索引取决于您的查询。使用explain来查看要编制索引的内容。
此外,不要害怕使用复合索引,并避免为你拥有的每列创建索引。
做到以上的步骤,你将有快速的查询(让我们至少希望)

+0

扭曲,非常感谢您的回答,什么意思是复合索引,是同时在多个列上的索引?对不起,我对数据库和PHP相当陌生。 –

+0

167是最大的城市名称,86是最大的国家名称btw。 –

+0

@KevinVermaat - 好吧,我不知道那个长度的国家/城市名称,很高兴知道。是的,复合索引意味着在多个列上有一个索引,即:'选择来自用户的用户名,其中a = 1和b = 2'将导致在列“a”和列“b”上的组合索引“ab”。 – Twisted1919

1

城市和乡村的表将是小(相对而言),可能存放在内存漂亮所以查找会快。

如果速度不够快,尝试缓存查找客户端(即您的php应用程序)。

由于您的行将会更小(int而不是varchar),因此您可以在每个页面上放置更多行,从而加快索引查找速度。

试着先把它做正规化,它可能会足够快。

并确保您使用InnoDB而不是MyISAM。它有更好的锁定,你的应用程序看起来非常并发。

+0

非常感谢信息,我会正常化。 –

+0

谢谢,我确实创建了新的结构,它的性能更好。但你确定这个innodb?我使用了很多count查询,这在innoDB中非常缓慢,因为它们是全表扫描。我相信你,如果你说InnoDB更适合我的应用程序,但是我有办法处理count(*)查询吗? –

+0

这不是详细介绍的地方,但您确信MyISAM的计数(*)查询速度更快。如果您进行任何类型的并发写入/读取(而不是纯读取),MyISAM中的表锁定将快速限制您的吞吐量。如果你只读MyISAM可能会更好。对于InnoDB计数(*),可以使用触发器维护一个表计数,但可能比MyISAM更糟糕。 –