关于如何改进我的数据库结构以及我应该索引哪些字段的问题?

时间:2011-07-24 13:29:17

标签: mysql database-design

我正在创建一个简单的比较脚本,我对数据库结构有一些疑问。首先,数据库将是巨大的,我预计products中的条目超过100万。 其次,会有一个搜索表单,搜索字词会查看(%$term%)字段 name 并显示产品的相关信息和商店信息。

您可以在下面看到名为products的数据库结构。

id int(10) NOT NULL
name varchar(50) NOT NULL
link varchar(50) NOT NULL
description varchar(50) NOT NULL
image varchar(50) NOT NULL
price varchar(50) NOT NULL

我的问题是:

  1. 你建议我索引一个字段吗?用户将无法插入或更新产品,唯一的查询将是SELECT以显示结果,我将经常更新XML Feed中的产品以进行可能的产品更改。

  2. 我必须存储商店信息,如姓名,运费,链接,图片...这给了我两个选项。 a)创建一个名为shops的新表,并使用products shopID 中的新字段将这两个表连接起来,以查找 id shops并显示信息或b)我是否应该在每个产品的products的额外字段中添加这些信息(名称,运费......)? (我认为答案很明显但我需要你的建议。)

  3. 我还应该考虑或改变其他事情吗?
  4. 我不是一名高级程序员,我所学的是通过互联网,所以也许问题对你来说太明显了,但对我来说是学习的门票。

    感谢您的回答。

6 个答案:

答案 0 :(得分:1)

尼古拉 ID应该是主键。这会自动为ID添加索引,并将加速任何需要获取特定产品的查询。

商店桌子应该是第二张桌子,但你应该有一张第3张桌子,可以将商品与商店联系起来。最基本的是,它有两个字段,shop_id,product_id。这让你在多个商店里有一个单品。这两个字段应该是产品表和商店表的外键。

如果您考虑过为每个商店的产品设定不同的价格,那么product_store连接表也应该包含价格,尽管基本价格可以存储在产品表中。

价格应为小数,以便您可以对价格字段进行计算。

答案 1 :(得分:1)

  1. 索引需要非常快速地获取记录。所以是的,他们被推荐了。但是你想使用什么样的指数? MyISAM引擎提供“常规”字符串索引,您可以使用LIKE子句(例如LIKE 'hello%'),但它限制您在搜索短语的开头使用通配符。此外,MyISAM有一个FULLTEXT索引,允许您在整个字符串中搜索单词,而不仅仅是字符串的开头。因此,您可以在列descriptionname上创建FULLTEXT索引 - 但在这种情况下,2个FULLTEXT索引似乎是多余的。也许您可以加入这些列并使用令牌或字符分隔值?如果是这样,您将需要在连接列上仅创建1个FULLTEXT索引,这可以节省大量碎片和磁盘空间。使用MyISAM引擎的一个缺点是,当写入它(UPDATE / DELETE查询)时 - 它会锁定整个表。因此,如果表每分钟写入多次,则可能会使其他查询挂起。这就是为什么你应该看看InnoDB引擎是否适合你的需求 - 它可以在桌面上实现并发读/写操作。
  2. 这可能是一个好主意,因为列price上的索引似乎很重要,而FULLTEXT索引不能与其他索引一起使用。
  3. 我会说:使用InnoDB和Sphinx,并在id& price上的常规索引。
  4. 最重要的是要了解的是,在为特定软件编写代码时,您必须熟悉该软件,并且需要注意。您应该阅读高性能MySQL - 非常推荐。


    修改 如果要在products表中添加索引,可以使用
    执行此操作 当表为空或包含少量数据时ALTER TABLE /* etc */。如果表中包含大量数据,则建议创建另一个类似于products的表,更改该新表并使用旧products表中的数据填充该表,例如:

    CREATE TABLE `products_new` LIKE `products`;
    ALTER TABLE `products_new` ADD FULLTEXT (`name`);
    LOCK TABLES `products` READ, `products_new` WRITE;
    INSERT INTO `products_new` SELECT * FROM `products`;
    LOCK TABLES `products` WRITE, `products_new` WRITE;
    ALTER TABLE `products` RENAME TO `products_bad`;
    ALTER TABLE `products_new` RENAME TO `products`;
    /* The following doesn't work:
          RENAME TABLE `products` TO `products_bad`, `products_new` TO `products`;
       See: http://bugs.mysql.com/bug.php?id=22246
    */
    DROP TABLE `products_bad`;
    

答案 2 :(得分:0)

1)您通常应该索引常用的字段。但是,由于您对名称的搜索在开始时使用通配符,因此索引对此查询没有影响。

2)创建商店表并链接到这将更好。

答案 3 :(得分:0)

  1. Price肯定是因为有些东西告诉我你会搜索这个字段并做排序。
  2. “过早优化是所有邪恶的根源”(c)Donald Knuth。所以,我建议规范你的表,所以YES - 为商店创建表。一旦你的应用变得越来越大,并且你面临高负荷,你将能够对数据库进行非规范化以避免JOINS(一种优化你的贪婪应用的方法)
  3. 根据您的问题返回stackoverflow; - )

答案 4 :(得分:0)

通常,您应该索引将被密集使用的字段。但是使用通配符进行搜索并没有多大帮助。 最好使用另一个带外键的表。 也不应该将product表中的“id”字段定义为PRIMARY KEY吗?

答案 5 :(得分:0)

以下是我的建议:

为了能够搜索%term%您需要full-text search,当搜索字词以通配符开头时,索引对您没有任何帮助。

  1. 是的,您应该在id-column上放置一个索引(并且可能使其自动递增),因为这似乎是表中的唯一列。除此之外,我们建议任何其他索引没有意义,因为我们不会运行哪些查询。
  2. 是的,为商店创建另一个表,否则您将拥有非normalized的数据,商店名称等等(可能会出现“需要”非标准化的极少数情况,例如优化,但你还没有到达那里)。在您的具体情况下,未标准化的数据会导致问题,例如当商店需要更改名称时您会做什么?那么,您必须更新产品表中的所有匹配行。
  3. 你应该记住很多事情,但是这个答案超出了范围。我建议你去工作和学习,因为边做边学是一个很好的方式成为一个更好的开发人员。然后,当您遇到特定问题时,请在stackoverflow上搜索/发布它。