SQL:插入(动态)查找表

时间:2016-12-17 21:41:05

标签: sql oracle

关于查找表的大多数文章都涉及其创建,初始填充和使用(查找:id ​​ - > value)。

我的问题是关于查找表的动态更新(插入新值),因为新数据存储在数据表中。

例如,我们有一个人员表,其中一个属性(列)是city of residency。许多人具有相同的值,因此使用查找表是有意义的。由于事先不知道将出现的城市列表,因此查找表最初为空。

澄清一下,city的值是:

  • 事先不知道(我们不知道明天客户可能会联系我们)
  • 没有"所有可能的城市列表" (现实生活中的城市来来去去,重新命名等)
  • 许多人将分享相同的价值
  • 最初,会有一些不同的值(最多10个),后来会更多(但不是很多,几百个) 此外,预期的人物对象数量将达到数千甚至数百万。

所以基本算法是(伪代码):

procedure insertPerson(name,age,city)
{
    cityId := lookup(city);
    if cityId == null
        cityId := insertIntoLookupTableAndReturnId(city);

    INSERT INTO person_table VALUES (name,age,cityId);
}

这个问题有什么好的查找表组织?准确的代码是什么? 目标是人员插入的高性能(无论城市是否已经在查询表中)。

欢迎大家回答,Oracle 11g会很棒。

注意:这是关于OLTP方案。实时插入新人。没有可用于初始化查找表的已知人员列表。

2 个答案:

答案 0 :(得分:1)

除了我要做的一个小改动之外,您的基本方法似乎没问题:函数lookup(city)将搜索城市并返回ID,如果找不到城市,则会插入新记录,返回其ID。这样,您将进一步封装查找表(城市)的管理。因此,您的代码将成为:

procedure insertPerson(name,age,city)
{
    INSERT INTO person_table VALUES (name,age,lookup(city));
}

您可以考虑的另一件事是创建一个用于查询人员的 VIEW 。信息,包括城市名称。

答案 1 :(得分:0)

经过一些测试,我能找到的最佳性能(最少的块访问)是将索引组织表作为查找表,使用下面的SQL来插入数据。

create table citylookup (key number primary key, city varchar2(100)) organization index;
create unique index cltx1 on citylookup(city);
create sequence lookupkeys;

create sequence datakeys;

create table data (x number primary key, k number references citylookup(key) not null);

-- "Rome" is the city we try to insert
insert all 
  when oldkey is null then -- if the city is not in the lookup yet
    into citylookup values (lookupkeys.nextval, 'Rome') -- then insert it
  -- finally, insert the data row with the correct lookup key
  when 1=1 then into data values (datakeys.nextval,nvl(oldkey, lookupkeys.nextval)) 
  select (select key from citylookup where city='Rome') as oldkey from dual;

结果:城市存在6 + 2个区块,城市区域10 + 2区域尚未存在(由 SQL * Plus 报告set autotrace on:第一个值是 db block gets ,第二个一致得到)。

或者,正如Dudu Markovitz所建议的那样,查找表可以在应用程序中缓存,在命中的情况下只需对DATA表执行一个简单的INSERT,然后只需要6 + 1块访问(对于上面的测试用例) 。这里的问题是使缓存的查找表与数据库以及服务器应用程序的其他可能实例保持同步。

PS:上面的INSERT ALL命令"浪费"即使没有新城市插入查找表,每次运行时lookupkeys序列的序列值也是如此。这是解决这个问题的另一个练习。