性能表布局(多个查询与单个大查询)

时间:2009-10-15 06:47:04

标签: mysql performance

我有一个直截了当的问题。

我正在做一个使用MySQL的Web应用程序,我正在设计它。我只是对性能有一个小问题。

我想知道哪些更有效:

场景#1:

Table: Restaurant
    -Name
    -City
    -Province
    -Country
    -Continent

sql =~ select * from restaurant where id = something.

场景#2:

Table: Restaurant   
    -Name
    -City
Table: City
    -Name
    -Province
Table: Province
    -Name
    -Country
Table: Country
    -Name
    -Continent
Table: Continent
   -Name

sql =~ [insert multiple sql queries that will output the name and the city,
        with the corresponding province, country, and continent]

从逻辑上讲,我认为场景#1更好(更少查询),但有些人却向我发誓。

5 个答案:

答案 0 :(得分:3)

是的,但问题是哪个选项表现更好。在这种情况下,毫无疑问:选项#1将表现更好,因为查询不必与任何其他表JOIN。 Randolph确实有一个好处,只要有可能,你应该规范化你的数据库结构。

答案 1 :(得分:2)

如果您对数据库设计没有经验,我建议您始终使用标准化版本。在大多数情况下,这是正确的做法。在某些情况下,您可能希望对数据库进行非规范化,但是您应该确切知道为什么要这样做。

请注意,在第二种情况下,它不是多个查询。它只是一个查询,其中所有表都连接在一起。例如:

SELECT *
FROM restaurant
    JOIN city ON city.id=restaurant.city
    JOIN province ON province.id=city.province
    ...

是的,编写需要更长的时间,但它比数据库中的数据不一致(维护非规范化数据库更难)。您也可以使用ORM为您执行此类操作。

答案 2 :(得分:0)

第二个选项是规范化结构,这意味着您的数据冗余更少,发生错误的机会更少等。我总是投票支持规范化数据,除非您遇到性能问题。

顺便说一下,SELECT * FROM [Table]无论如何都不是好习惯。你需要输入列名。

答案 3 :(得分:0)

如果您使用第一个方案,则会出现空间使用增加的问题(对于所有重复的省份,国家/地区),如果您需要更改城市/国家/地区的名称,则需要在所有行中更改它被使用了。

为方便起见,我将使用第二种情况。我不认为两种情况之间会有很大的性能差异(在第一种情况下,您只触摸一个表,但从磁盘读回更多数据,在第二种情况下,您从磁盘读取的数据较少,但是从多个表中读取数据) )。这实际上取决于你在那里有什么样的数据。

编辑:为了解释我的观点:如果将所有数据保存在一个大表中,那么你需要实际读取磁盘中的所有行,即使读取的大部分数据是相同的(即市,省,国家,大陆)。即使SQL缓存数据,它也无济于事,因为它无法知道来自其他行的数据是相同的。

如果您规范化数据库并从餐厅表中读取,您将获得城市的ID。现在,如果您在多行上拥有相同的ID,SQL服务器将缓存为城市读取的数据,并且不会再次访问磁盘,因此速度会提高。这将被访问新表的需要所抵消,但是对城市ID的正确索引应该不会太多。

这就是为什么我说使用大型数据库时,性能差异并不容易评估,你最好还是有一个正确规范化的数据库。

是的,如果您使用标准化数据库(第二种情况),您可以在一个地方更改城市名称,因为城市将有一行。这同样适用于其他国家(省,国家,大陆)。

答案 4 :(得分:0)

谢谢你们的意见。 “规范化数据库设计”是关键。我用Google搜索,快速阅读它,虽然性能稍差,但专业人士确实值得。

再次感谢。 (那真的很快btw!) http://en.wikipedia.org/wiki/Database_normalization

维基百科声称非规范化具有更好的性能,但我认为我只是变得自大,并认为我可以处理一个大的非规范化数据库。

我会坚持风险较小的情景。如果shits击中风扇,我将改变硬件=)。

再次感谢你们。