【发布时间】:2014-05-11 16:15:00
【问题描述】:
我的应用程序和数据库设计可以简化为一个简单的报价系统。
以下是详细说明:
数据库中的三个表:
表格:项目:
- itemId(唯一,主键,自动增加)
- 名称 varchar 不为空
- 类别 varchar 不为空
- 说明 varchar 不为空
表格:收件人:
- recipientId(唯一,主键,自动增加)
- 名字 varchar 不为空
- 姓氏varchar不为空
- 地址 varchar 不为空
- 电子邮件 varchar 不为空
表格:顺序:
- id(唯一,主键,自动增加)
- 价格双倍不为空
- 日期时间戳
- itemId(非外键)
- recipientId(非外键)
我有以下存储过程来处理选择/业务逻辑:
CREATE procedere spInsert
--list of parameters
set @tmpItemId = (select itemId from item
where name = @name
and category = @category
and description = @description)
if @tmpItemId is NULL
begin
insert to item values(@name, @category, @description)
set @tmpItemId = @@IDENTITY
end
set @tmpRecipentId = (select recipentId from recipient
where firstname = @firstname
and lastname = @lastname
and address = @address and email = @email )
if @tmpRecipentId is NULL
begin
insert to recipient values(@firstname, @lastname, @address, @email)
set @tmpRecipentId = @@IDENTITY
end
insert into order values(@price, @date, @tmpItemId, @tmpRecipientId )
所以基本上逻辑是检查Item和Recipient的存在,然后插入。
在真实数据库中,Item和Recipient的列号分别为20,20。我正在尝试通过读取文本文件中的大量原始信息(将商品信息、收件人信息和订单信息混合在一起)来进行压力测试,然后执行spInsert:
JdbcTemplate jt = getJdbcTemplate();
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jt);
simpleJdbcCall.withProcedureName("spInsert").execute(paraMap);
但是速度却不尽如人意。粗略计算,每100行原始信息插入需要3-5秒。
我想知道是否有任何改进的余地?包括改变数据库的设计?
PS,我正在考虑将 Item 和 Recipient 的自动增加索引 ID 更改为 UUID,以便让程序知道新 ID Item 和 Recipient 并避免 @ 987654333@ 在存储过程中。是否可行?
这是执行计划:
【问题讨论】:
-
请执行计划。您希望我们重建您的数据库并为您制定执行计划吗?很可能你错过了提高查询效率的方法,但我们至少应该知道执行计划。而且您错过了像这样的 SP 可能需要避免参数嗅探问题的“重新编译”选项。
-
执行计划请参考更新
-
他并没有因为参数嗅探而得到糟糕的执行计划,而是因为根本没有索引,甚至在他创建了必要的索引之后也可能不会。顺便说一句,避免 WITH RECOMPILE,如果你真的必须处理糟糕的缓存计划问题,请在语句级别使用 OPTION (RECOMPILE),这样开销要少得多。
标签: sql sql-server database stored-procedures database-design