2012-01-10 91 views
1

表模式是这样的:桌子设计之间的区别?

应用:

applicationid(pk) 
userid(pk) 
applicationname 

服务:

serviceid(pk) 
userid(pk) 
applicationid 
servicename 
servicetype 
version 
modifieddate 

我要编写一个查询来过滤所有记录针对特定applciation特定用户。 userid将有一个'common'值,在这种情况下,所有用户都将访问它,并且此常见记录将具有版本'1'。 如果用户'a'编辑记录'common',则编辑的信息将被插入为带有用户标识'a'和版本'2'的新记录。 在这种情况下,在过滤时,我必须显示,而不是'普通'记录,但用户的记录版本为'2'。 对于不对应于任何应用程序的服务,applicationid字段将为'null',它们将被称为外部服务。

对于上述数据模型,我无法编写将使用索引而不是范围的过滤器查询。

编辑: 我必须筛选特定用户的特定应用程序中的所有记录。在过滤时,我们必须考虑版本和用户标识符上的上述要点。所以,过滤约束变得太复杂了。

使用应用程序表是因为我必须在applicationid不为空时显示应用程序名称[如果服务对应于应用程序]。

说,查询变得像,

select ser.*,app.applicationname 
from services ser 
left join applications app 
on ser.userid = app.userid and ser.applicationid = app.applicationid 
where (ser.userid = 'user1' OR ser.userid = 'common') 
AND (ser.applicationid = 'appid1' OR ser.applicationid IS NULL) 
AND (ser.modifieddate < '9999-01-01 00:00:00' OR (ser.modifieddate = '9999-01-01 00:00:00' AND ser.serviceid > ' \n')) 
AND ser.version = (select max(ser1.version) 
        from services ser1 
        where (ser1.userid = 'user1' OR ser1.userid = 'common') 
        AND (ser1.applicationid = 'appid1' OR ser1.applicationid IS NULL) 
        AND ser1.servicename = ser.servicename) 
ORDER BY ser.modifieddate,ser.serviceid 
LIMIT 0,50 

但性能较差,此查询。我想优化它。子查询和联接使用索引(applicationid,servicename)(userid,applicationid)大约需要2s。但无论我做什么,我都无法让外部查询占用任何索引。有什么建议么?

请你帮我

  1. 要在一个更好的查询计划到达?
  2. 或重新设计表格?
+0

服务表DDL不清楚。请详细说明我们的要求 – 2012-01-10 09:35:09

+0

我已经添加了一些更多的细节..希望这有助于更好地理解.. :) – Sowmiya 2012-01-10 10:15:49

回答

0

从你写什么,我会通过创建以下表中接近数据模型:

  • 用户(拥有用户的列表)
  • 应用(持有的应用程序列表)
  • applicationVersion(持有映射到用户id的应用程序版本列表)
  • 服务(持有服务的列表)
  • serviceApplicatioVersion(HO lds哪个应用程序版本映射到哪个服务)

你甚至可能想引入一个serviceVersion表,然后将一个服务版本映射到应用程序的版本。我无法从你写的东西中知道服务是否有版本或应用程序。总之,这里是一些DDL和诺迪例如数据来说明我的意思:

create table user 
(id int unsigned not null primary key auto_increment, 
userName varchar(50) not null, 
unique key userUIdx (userName)); 

create table application 
(id int unsigned not null primary key auto_increment, 
applicationName varchar(50) not null, 
unique key applicationUIdx1 (applicationName)); 

create table applicationVersion 
(id int unsigned not null primary key auto_increment, 
applicationId int unsigned not null, 
version decimal(10,2) unsigned not null default 1.0, 
userId int unsigned not null, 
modifiedDate timestamp, 
unique key applicationVersionUIdx1 (applicationId,version), 
constraint `fk_applicationVersion_user1` FOREIGN KEY (`userId`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, 
constraint `fk_applicationVersion_application1` FOREIGN KEY (`applicationId`) REFERENCES `application` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 
); 

create table service 
(id int unsigned not null primary key auto_increment, 
serviceName varchar(50) not null, 
serviceType varchar(50) not null, 
unique key serviceUIdx1 (serviceName)); 

create table serviceApplicationVersion 
(id int unsigned not null primary key auto_increment, 
applicationVersionId int unsigned not null, 
serviceId int unsigned not null, 
modifiedDate timestamp, 
unique key serviceApplicationVersionUIdx1 (applicationVersionId,serviceId), 
constraint `fk_serviceApplicationVersion_applicationVersion1` FOREIGN KEY (`applicationVersionId`) REFERENCES `applicationVersion` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION, 
constraint `fk_serviceApplicationVersion_service1` FOREIGN KEY (`serviceId`) REFERENCES `service` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION 
); 

insert into user (userName) values ('common'); 
insert into user (userName) values ('User A'); 
insert into user (userName) values ('User B'); 

insert into application (applicationName) values ('App 1'); 
insert into application (applicationName) values ('App 2'); 

insert into applicationVersion (applicationId,version,userId) values (
(select id from application where applicationName = 'App 1'), 
1.0, 
(select id from user where userName = 'common') 
); 

insert into applicationVersion (applicationId,version,userId) values (
(select id from application where applicationName = 'App 1'), 
2.0, 
(select id from user where userName = 'User A') 
); 

insert into service (serviceName, serviceType) values ('Service 1','Service with apps'); 
insert into service (serviceName, serviceType) values ('Service 2','Service with no apps'); 

insert into serviceApplicationVersion (applicationVersionId,serviceId) values (
(select av.id from applicationVersion av inner join application a on a.id = av.applicationId where a.applicationName = 'App 1' and av.version = 2.0), 
(select id from service where serviceName = 'Service 1') 
); 

-- Query to select services,applications and versions in those services and users 
select s.serviceName, 
a.applicationName, 
av.version, 
u.userName 
from user u 
inner join applicationVersion av on av.userId = u.id 
inner join serviceApplicationVersion sav on sav.applicationVersionId = av.id 
inner join application a on av.applicationId = a.id 
inner join service s on s.id = sav.serviceId 
where userName = 'User A'; 

你可能不得不调整它取决于你想要什么很大,但希望它会让你在正确的去方向。

+0

@汤姆 - 感谢您的输入:)该版本是为服务。因此,我可以创建一个表'ServiceVersion [serviceid,userid,version]',它将跟踪特定用户的服务版本。如果此表没有特定用户的任何条目,我可以将'普通'userid的记录,以防万一,存在两个记录,一个'Common'和一个userid'a'。我将分析这是如何工作的,并简化了我的查询。 – Sowmiya 2012-01-10 10:32:03

1

我分区基础上,我要存储数据的服务表,如下图所示:

CREATE TABLE `app_ws_common` (                          
      `serviceid` varchar(16) NOT NULL,                        
      `applicationid` varchar(16) default NULL,                      
      `modifieddate` date default NULL,                        
      `version` decimal(1,0) default NULL,                       
      `servicename` varchar(20) default NULL,                      
      `userid` varchar(128) NOT NULL,                        
      PRIMARY KEY (`serviceid`,`userid`),                       
      KEY `table1_isv_fk` (`applicationid`,`userid`),                    
      CONSTRAINT `table1_isv_fk` FOREIGN KEY (`applicationid`, `userid`) REFERENCES `applications` (`applicationid`, `userid`) 
     ) ENGINE=InnoDB DEFAULT CHARSET=latin1 



CREATE TABLE `app_ws_user` (                          
      `serviceid` varchar(16) NOT NULL,                        
      `userid` varchar(128) NOT NULL,                        
      `applicationid` varchar(16) default NULL,                      
      `modifieddate` date default NULL,                        
      `version` decimal(1,0) default NULL,                       
      `servicename` varchar(20) default NULL,                       
      PRIMARY KEY (`serviceid`,`userid`),                       
      KEY `FK_app_ws_user` (`applicationid`,`userid`),                    

      CONSTRAINT `FK_app_ws_user` FOREIGN KEY (`applicationid`, `userid`) REFERENCES `applications` (`applicationid`, `userid`) 
     ) ENGINE=InnoDB DEFAULT CHARSET=latin1 


CREATE TABLE `applications` (     
      `applicationid` varchar(16) NOT NULL,   
      `userid` varchar(128) NOT NULL,    
      `applicationname` varchar(30) default NULL, 
      PRIMARY KEY (`applicationid`,`userid`)  
     ) ENGINE=InnoDB DEFAULT CHARSET=latin1 

CREATE TABLE `external_ws_common` (   
       `serviceid` varchar(16) NOT NULL,   
       `modifieddate` date default NULL,   
       `version` decimal(1,0) default NULL,  
       `servicename` varchar(20) default NULL, 
       PRIMARY KEY (`serviceid`)    
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1 


CREATE TABLE `external_ws_user` (   
       `serviceid` varchar(16) NOT NULL,   
       `userid` varchar(128) NOT NULL,   
       `applicationid` varchar(16) default NULL, 
       `modifieddate` date default NULL,   
       `version` decimal(1,0) default NULL,  
       `servicename` varchar(20) default NULL,  
       PRIMARY KEY (`serviceid`,`userid`)  
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1 

这里:

app_ws_common表包含所有应用程序相关的服务,这是共同所有用户

app_ws_user表包含特定用户创建的所有应用程序相关服务并从中进行编辑通用版本。

应用程序表将包含应用程序列表和相应的用户。

external_ws_common表将包含独立于所有应用程序且对所有用户通用的服务列表。

external_ws_user表格将包含与任何应用程序不对应的服务列表,并且由用户从“公共”版本的外部服务创建或编辑。

现在,我们必须从表app_ws_user和表app_ws_common中的所有服务检索与app_ws_user表中特定用户的编辑版本不同的应用程序相关服务。

如何有效地编写查询?