Поясню что я имею в виду.
Допустим есть таблица с объявлениями. У каждого объявления есть связанные с ним данные:
1) Теги
1.1) Категория тега
2) Номера телефонов
3) Изображения
4) Автор
Структура примерно такаяSET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for advert
-- ----------------------------
DROP TABLE IF EXISTS `advert`;
CREATE TABLE `advert` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`author_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `author_id` (`author_id`),
CONSTRAINT `advert_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for author
-- ----------------------------
DROP TABLE IF EXISTS `author`;
CREATE TABLE `author` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`login` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for category
-- ----------------------------
DROP TABLE IF EXISTS `category`;
CREATE TABLE `category` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for image
-- ----------------------------
DROP TABLE IF EXISTS `image`;
CREATE TABLE `image` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`advert_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `advert_id` (`advert_id`),
CONSTRAINT `image_ibfk_1` FOREIGN KEY (`advert_id`) REFERENCES `advert` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for link_advert_phone
-- ----------------------------
DROP TABLE IF EXISTS `link_advert_phone`;
CREATE TABLE `link_advert_phone` (
`phone_id` int(10) unsigned NOT NULL,
`advert_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`advert_id`,`phone_id`),
KEY `phone_id` (`phone_id`),
CONSTRAINT `link_advert_phone_ibfk_1` FOREIGN KEY (`phone_id`) REFERENCES `phone` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `link_advert_phone_ibfk_2` FOREIGN KEY (`advert_id`) REFERENCES `advert` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for link_advert_tag
-- ----------------------------
DROP TABLE IF EXISTS `link_advert_tag`;
CREATE TABLE `link_advert_tag` (
`tag_id` int(10) unsigned NOT NULL,
`advert_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`tag_id`,`advert_id`),
KEY `advert_id` (`advert_id`),
CONSTRAINT `link_advert_tag_ibfk_1` FOREIGN KEY (`tag_id`) REFERENCES `tag` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `link_advert_tag_ibfk_2` FOREIGN KEY (`advert_id`) REFERENCES `advert` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for phone
-- ----------------------------
DROP TABLE IF EXISTS `phone`;
CREATE TABLE `phone` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`value` varchar(16) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- ----------------------------
-- Table structure for tag
-- ----------------------------
DROP TABLE IF EXISTS `tag`;
CREATE TABLE `tag` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`category_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `category_id` (`category_id`),
CONSTRAINT `tag_ibfk_1` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS=1;
Необходимо вытащить все связанные с объявлениями данные.
База весит примерно 4Гб. Сейчас всё это дело вытягивает самопис который строит запрос основываясь на структуре базы. Происходит это примерно так:
$result = $db->getTable('advert')
->select()
->limit(180)
->offset(0)
->cache(5)
->link('author')
->link('image')
->link('link_advert_phone.phone')
->link('link_advert_tag.tag.category')
->query()
;
В результате получаем такой массив:
$result = [
[
'id' => 1,
'title' => '....',
'author_id' => 1,
'author_id.author.id' => [
'id' => 1,
'login' => 'user name',
],
'id.image.advert_id' => [
[
'id' => 1,
'advert_id' => 1,
],
[
'id' => 2,
'advert_id' => 1,
],
// ....
],
'id.link_advert_phone.advert_id' => [
[
'advert_id' => 1,
'phone_id' => 1,
'phone_id.phone.id' => [
'id' => 1,
'value' => '+996......',
]
],
// ....
],
'id.link_advert_tag.advert_id' => [
[
'advert_id' => 1,
'tag_id' => 1,
'tag_id.tag.id' => [
'id' => 1,
'name' => 'Тег',
'category_id' => 1,
'category_id.category.id' => [
'id' => 1,
'name' => 'Категоряия',
]
]
],
// ....
],
],
// ...
];
Самопис при необходимости строит временные таблицы с ключами и составляет сложные запросы вытягивающие вот такие структуры произвольной вложенности. Плюс можно писать условия к вложенным таблицам которые будут влиять на результат. Писать такие запросы в ручную можно но очень проблематично и сложно. Сейчас в планах переписать весь сайт и хотелось бы этот самопис заменить сторонним решением. Пробовал doctrine, он увеличивает время с 200 мс примерно до 3-х секунд, плюс сложность написания запросов возрастает на порядок.