【问题标题】:Best practice with lookup table implementation to improve performance查找表实现以提高性能的最佳实践
【发布时间】:2016-04-19 17:35:39
【问题描述】:

我想知道创建查找表的最佳方法是什么。 例如,我有一个表missionProfile,其中一个字段(主键)字符串idMissionProfile 和一个字段note。我所有的价值观必须彼此不同。 但是通过这种方法,所有链接到missionProfile 的表都将整个字符串键作为外键,我认为与Integer 主键相比,它会占用更多内存并且需要更多时间来写入整个字符串。 但是,如果我使用整数主键,我必须在创建它之前检查字段missionProfile 是否存在,因为键是增量的,并且可能是我的字段的重复值。 在大型数据库中,根据您的经验,最好使用 String 或始终检查该字段是否存在然后写入数据库? 谢谢

例子

任务简介:

idMissionProfile
------------------------------------------
FIRST_OIL_CHANGE_SAMPLE_&_PARAMETERS_RESET  
NEDC    
VEHICLE_TRANSFER

idMissionProfile   MissionProfile
-------------------------------------------
1                  FIRST_OIL_CHANGE_SAMPLE_&_PARAMETERS_RESET   
2                  NEDC 
3                  VEHICLE_TRANSFER

所以在我的收购中

idAcquisition id_MissionProfile
---------------------------------
1             1
2             2
3             2

否则我会有

idAcquisition id_MissionProfile
---------------------------------
1             FIRST_OIL_CHANGE_SAMPLE_&_PARAMETERS_RESET
2             NEDC
3             NEDC

第二种方法似乎更好,但是当我添加新的任务配置文件时,我必须检查是否存在,而不是在第一种方法中,如果存在,它不会添加新的字符串值,因为它是键。 这是一个简单的案例,但是如果我有一个由几列组成的主键呢? 我正在将一个 excel 文件映射到数据库中,因此我需要选择最佳方法来提高我的性能

有了增量 id 我有:

MissionProfile missionProfile=null;
        if ((value=actualRowValues.get(ExcelMappingCoordinate.missionProfile.getCoordinate()+index))!=null){
            missionProfile= missionProfileServices.findByMissionProfile(value);
            //TODO se esiste allora carica quello che esiste altrimenti lo crea
            if (missionProfile == null){
                missionProfile= new MissionProfile();
                missionProfile.setMissionProfile(value);
                missionProfileServices.create(missionProfile);
        }

我有键值

MissionProfile missionProfile=new MissionProfile();
if ((value=actualRowValues.get(ExcelMappingCoordinate.missionProfile.getCoordinate()+index))!=null){
    missionProfile.setMissionProfile(value);
    missionProfileServices.create(missionProfile);
}

【问题讨论】:

  • 我不太明白你的问题!如果您使用字符串值作为键,那么您不需要在使用之前检查该值是否存在吗?使用 auto_increment 整数类型字段,保证键是唯一的。
  • 也许我解释得不够好。我所有的值都必须彼此不同,所以如果我在调用 save 方法时将值存储为主键,它不会添加该值(如果存在)。如果我存储整数主键和我的值,我必须检查是否存在。
  • 如果您使用 auto_increment 字段作为主键(或 Neville 在他的回答中指出的 UUID),那么当您将记录插入表中时,该键的值由 mysql 确定。
  • 我用一个例子更新了我的问题

标签: java mysql database hibernate primary-key


【解决方案1】:

您在这个问题中混淆了一大堆东西。我不完全确定我是否理解您的要求 - 架构甚至更好的 SQLFiddle 会很棒。

第一个是“字符串是否比整数占用更多空间?”。答案是肯定的,但在现代硬件上这并不重要,除非您在尺寸、性能或可扩展性方面处于极端状态。

第二个是“我应该如何生成我的主键?”。这是一个surprisingly complex 的问题;但几乎每个人都同意您的主键应该是“自然的”(域实体的属性,保证唯一且永远不会改变),或者完全没有意义的东西,如自动递增整数或 GUID。

从问题的字里行间看,查找表的主键似乎具有某种意义,因为您正在使用它来检查值是否存在。这是一个坏主意,因为这意味着如果不检查每个相关实体,您永远无法更改该值。

例如,如果您有一个“员工”表和一个“部门”表,如下所示:

员工

EmployID  Name  Department    LeavingDate
------------------------------------------
1        Fred   HR            NULL
2        Angie  HR            1 Jan 2010
3        Bert   IT            NULL

部门

DepartmentID     Name
------------------------------------------------ 
HR               HR Department
IT               IT Department

如果人力资源部门在 2016 年 1 月 1 日更名为“PEOPLE”,您将如何处理 Angie?她是在部门被称为 HR 的时候离开的,所以你不能真正将其更改为 PEOPLE。但是您不想在更新 HR 部门名称时检查离开的人员。

拥有一个无意义的钥匙要整洁得多。这样,您可以在 Departments 中构建“名称历史”逻辑,而不必影响链接到它的所有表。

员工

EmployID  Name  Department    LeavingDate
------------------------------------------
1        Fred   1             NULL
2        Angie  1             1 Jan 2010
3        Bert   2             NULL

部门

DepartmentID     Name                ValidFrom   ValidUntil
-----------------------------------------------------------
1                HR Department       1/1/1990    1/1/2016
1                People Department   1/1/2016    NULL
2                IT Department       1/1/1990    NULL

我认为您要问的第三个问题是“我应该创建一个查找表,还是应该使用具有固有含义的属性?”这在从 Excel 导入时尤其重要。

正式的答案是normalize your data schema,如果你有一个实际的、可测量的问题,你只需要担心性能。这一点通常在体面的硬件上达到数千万或数亿条记录。

更务实的答案是,这取决于您打算如何使用数据。

如果您始终需要将FIRST_OIL_CHANGE_SAMPLE_&_PARAMETERS_RESET 替换为对用户更友好的字符串,我会创建一个带有自动递增主键的查找表。

如果涉及业务逻辑 - FIRST_OIL_CHANGE_SAMPLE_&_PARAMETERS_RESET 记录与 VEHICLE_TRANSFER 记录的处理方式不同,我会使用自动递增整数。这降低了拼写错误的风险,并允许您将逻辑标志添加到查找表中。

但是,如果您只是将这一列读出来,没有任何逻辑或替代,我会直接将该值读入表中...

【讨论】:

  • 但是使用自动递增键,我的字段的多行值可能相同,因此为避免这种情况,我必须在尝试添加到表之前检查值是否存在。所有这些控制都会降低我的软件性能?
猜你喜欢
  • 2017-08-14
  • 2014-10-02
  • 2012-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
相关资源
最近更新 更多