Разница между конструкциями стола? - PullRequest
1 голос
/ 10 января 2012

Схема таблицы выглядит так:

Применение:

applicationid(pk)  
userid(pk) 
applicationname

Услуги:

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

Мне нужно написать запрос, чтобы отфильтровать все записи для конкретного пользователя для конкретного приложения. userid будет иметь одно значение «common», и в этом случае все пользователи будут иметь к нему доступ, и эта общая запись будет иметь версию «1». Если пользователь «a» редактирует запись «common», то отредактированная информация будет вставлена ​​как новая запись с идентификатором пользователя «a» и версией «2». В этом случае при фильтрации я должен показать не «обычную» запись, а запись пользователя с версией «2». Поле applicationid будет 'null' для сервисов, которые не соответствуют никаким приложениям, они будут называться внешними сервисами.

В приведенной выше модели данных я не могу написать запрос фильтра, который будет использовать индекс вместо диапазона.

EDIT: Я должен отфильтровать все записи в конкретном приложении конкретного пользователя. Мы должны учитывать вышеупомянутые пункты в версии и идентификаторе пользователя при фильтрации. Таким образом, ограничение фильтрации становится слишком сложным.

Таблица приложений используется потому, что мне нужно отобразить имя приложения, если 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

Но производительность этого запроса низкая. Я хочу оптимизировать это. Это занимает около 2 секунд, когда подзапрос и объединение используют индексы (applicationid, servicename) и (userid, applicationid) . Но что бы я ни делал, я не могу заставить внешний запрос занимать какой-либо индекс. Какие-либо предложения?

Пожалуйста, помогите мне

  1. Чтобы прийти к лучшему плану запросов?
  2. Или переделать стол?

Ответы [ 2 ]

1 голос
/ 11 января 2012

Я разделил таблицу служб на основе данных, которые я собираюсь сохранить, как показано ниже:

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.

Как мне эффективно написать запрос для этого?

0 голосов
/ 10 января 2012

Из того, что вы написали, я подхожу к модели данных, создавая следующие таблицы:

  • пользователь (содержит список пользователей)
  • приложение (содержит список приложений)
  • applicationVersion (содержит список версий приложений, сопоставленных с userId)
  • услуга (содержит список услуг)
  • serviceApplicatioVersion (содержит информацию о том, какая версия какого приложения сопоставлена ​​с какой службой)

Возможно, вы даже захотите ввести таблицу 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';

Вам, вероятно, придется сильно его настраивать в зависимости от того, что вы хотите, но, надеюсь, это поможет вам двигаться в правильном направлении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...