表模式如下:
应用:
applicationid(pk)
userid(pk)
applicationname
服务:
serviceid(pk)
userid(pk)
applicationid
servicename
servicetype
version
modifieddate
我必须编写一个查询来过滤特定用户的特定用户的所有记录。 userid将具有一个值'common',在这种情况下,所有用户都将访问它,并且此公共记录将具有版本'1'。 如果用户'a'编辑记录'common',则编辑的信息将作为具有用户标识'a'和版本'2'的新记录插入。 在这种情况下,在过滤时,我必须显示,而不是“常用”记录,而是显示版本为“2”的用户记录。 对于与任何应用程序不对应的服务,applicationid字段将为“null”,它们将被称为外部服务。
使用上述数据模型,我无法编写将使用索引而不是范围的过滤器查询。
编辑: 我必须过滤特定用户的特定应用程序中的所有记录。我们必须在过滤时考虑版本和用户ID上的上述要点。因此,过滤约束变得过于复杂。
使用Applications表是因为我必须显示applciation名称,以防applicationid不为null [如果服务对应于某个应用程序]。
说,查询变得像,
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)时大约需要2秒。但无论我做什么,我都无法使外部查询占用任何索引。有什么建议?
请你帮帮我
答案 0 :(得分: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_user表中没有该特定用户的编辑版本时从表app_ws_common中检索所有服务。
如何有效地为此编写查询?
答案 1 :(得分:0)
根据您所写的内容,我将通过创建以下表格来接近数据模型:
您甚至可能想要引入serviceVersion表,然后将服务版本映射到应用程序版本。我无法判断您所写的服务是否有版本或应用程序。无论如何,这里有一些DDL和noddy示例数据来说明我的意思:
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';
你可能不得不根据你的需要调整它,但希望它会让你朝着正确的方向前进。