0

我正在尝试提高现有 MySQL 数据库的性能。

这是一个关于餐馆的数据库,有两个相关的表:

网站的所有实体都有一个表格,每个实体都有一个唯一的 id,一个实体几乎可以是任何东西,它可以是餐厅、用户和许多其他东西。有几种实体类型,对于餐馆,它们的实体类型是“对象”。

我还要说,数据库的这种结构几乎已经存在,所以我不想做大的改变,例如,我不会删除所有实体的表。(数据库本身没有数据,但是 PHP 引擎是构建的,因此很难对结构进行大的更改)。

还有一个仅用于对象的表,该数据库中有几种类型的对象,但是由于这是网站的主题,因此专门针对餐馆将进行大量搜索,餐馆有多个字段:国家,城市,名称,流派。在同一个城市和国家不能有两家同名的餐厅,(例如可以有两家同名但在同一个国家的不同城市,或者在两个同名但在同一个城市不同的国家)

所以从这个事实我想我应该为国家、城市和名称列创建一个唯一的三列索引。

另外我想说的是,URL也是以www.domain.com/Country/City/Restuarant-Name的形式构建的,所以country-city-name的组合应该被快速获取并且这种类型的查询会发生很多。

但也会有很多其他类型的查询,例如:在某个城市或某个特定城市搜索餐厅名称(使用 LIKE 查询,因为搜索的名称可以是全名的一部分)国家。搜索某个国家和城市中某种类型的所有餐厅。几乎所有可能的组合。

最常用的查询可能是 (a) 搜索某个城市和国家/地区的餐厅名称(这与键入 URL 时使用的查询相同,但将使用 LIKE),(b) 搜索某个城市和国家/地区的餐厅特定城市和国家的特定类型。最后(c)在全球范围内搜索餐厅名称(在整个数据库中,不指定城市和国家)

该表(对象表)当前具有PRIMARY KEY,即对象的ID,该ID也被大量使用,最佳做法如下?:

  1. 从国家、城市、名称中创建一个三列 UNIQUE 索引
  2. 从名称中创建另一个(非唯一)索引(因此我在上面编写的类型 c 的查询将被快速执行)
  3. 可能会从对象表中创建某种仅包含餐厅的子表,以便查询该子表。(这不那么重要,因为如果我决定做一个大的改变,我可能会把餐馆从对象的其余部分分开)

我真的很感激任何帮助,因为我长期以来一直试图决定这一点。

ps 对象表中的某些对象不会有任何类型或任何国家或城市,因此它们将保持为 NULL,我知道 UNIQUE KEY 中允许使用 NULL 值,但它会对性能产生影响吗?

非常感谢任何愿意阅读这个长问题的人:)

4

1 回答 1

1

您可以随心所欲地思考和计划,但在您尝试、基准测试和比较您的选择之前,您无法确定什么是最好的。也就是说,听起来你肯定是在正确的轨道上。

复合键
您的“国家-城市-名称”复合键似乎是最有用的顺序,因为它的选择标准从最宽到最窄排列。我确定您是故意这样做的,因为复合键的值只能从左到右使用。正如您所指出的,因为name在该索引中没有排在第一位,所以您需要一个单独的键name

NULL的索引值
根据imysql.cn的说法,“在索引中允许 NULL 值确实不会影响性能。” 这只是简单地陈述为没有数据或参考的旁白,所以我不知道他们如何/是否证明了这一点。

拆分表
如果餐厅记录中混入了很多其他数据,当然,这可能会减慢速度。如果您表分片为结构相同的“餐厅”和“其他”表,您仍然可以在必要时使用简单的 UNION 轻松查询它们的组合数据。除非您对预期的数据/减速有所了解,否则我宁愿避免对表进行分片,除非必要,至少为了简单/统一起见。

是否存在当前索引无法考虑的可预见查询,例如没有国家/地区的城市?如果是这样,请务必适当索引以涵盖所有可预见的情况。你没有提到它,但我想你也会有一个关于流派的索引。


最终,您需要生成大量测试数据并进行尝试。(确定您最终可以预期多少数据,并生成至少三倍的测试数据以使系统通过其步伐。)根据您的描述,设计听起来不错,但测试可能会发现意想不到的问题,在哪些地方您将从不同的索引等中受益。发现任何问题后,您将有一个特定的目标要完成,而不是简单地思考所有假设场景。

于 2011-06-17T19:32:45.400 回答