我整理了一下问题,因为它变得很大且难以理解。
正如您在下面的图像中所看到的,当从包含15000行(条件返回6650的where的表)中选择表时,查询将使用755.15 ms
表Company,包含1000行。表geo__name包含84300行aprox,并且没有给我任何问题,因此我认为问题是数据库结构或其他问题。
这两个表的结构如下:
表作业为:
CREATE TABLE `job` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`company_id` int(11) NOT NULL,
`activity_sector_id` int(11) DEFAULT NULL,
`status` int(11) NOT NULL,
`active` datetime NOT NULL,
`contract_type_id` int(11) NOT NULL,
`salary_type_id` int(11) NOT NULL,
`workday_id` int(11) NOT NULL,
`geoname_id` int(11) NOT NULL,
`title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`minimum_experience` int(11) DEFAULT NULL,
`min_salary` decimal(7,2) DEFAULT NULL,
`max_salary` decimal(7,2) DEFAULT NULL,
`zip_code` int(11) DEFAULT NULL,
`vacancies` int(11) DEFAULT NULL,
`show_salary` tinyint(1) NOT NULL,
PRIMARY KEY (`id`),
KEY `created_at` (`created_at`,`active`,`status`) USING BTREE,
CONSTRAINT `FK_FBD8E0F823F5422B` FOREIGN KEY (`geoname_id`) REFERENCES `geo__name` (`id`),
CONSTRAINT `FK_FBD8E0F8398DEFD0` FOREIGN KEY (`activity_sector_id`) REFERENCES `activity_sector` (`id`),
CONSTRAINT `FK_FBD8E0F85248165F` FOREIGN KEY (`salary_type_id`) REFERENCES `job_salary_type` (`id`),
CONSTRAINT `FK_FBD8E0F8979B1AD6` FOREIGN KEY (`company_id`) REFERENCES `company` (`id`),
CONSTRAINT `FK_FBD8E0F8AB01D695` FOREIGN KEY (`workday_id`) REFERENCES `workday` (`id`),
CONSTRAINT `FK_FBD8E0F8CD1DF15B` FOREIGN KEY (`contract_type_id`) REFERENCES `job_contract_type` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
餐桌公司是:
CREATE TABLE `company` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`logo` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` datetime NOT NULL,
`updated_at` datetime NOT NULL,
`website` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`user_id` int(11) NOT NULL,
`phone` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`cifnif` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`type` int(11) NOT NULL,
`subscription_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQ_4FBF094FA76ED395` (`user_id`),
KEY `IDX_4FBF094F9A1887DC` (`subscription_id`),
KEY `name` (`name`(191)),
CONSTRAINT `FK_4FBF094F9A1887DC` FOREIGN KEY (`subscription_id`) REFERENCES `subscription` (`id`),
CONSTRAINT `FK_4FBF094FA76ED395` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
查询如下:
SELECT
j0_.id AS id_0,
j0_.status AS status_1,
j0_.title AS title_2,
j0_.min_salary AS min_salary_3,
j0_.max_salary AS max_salary_4,
c1_.id AS id_5,
c1_.name AS name_6,
c1_.logo AS logo_7,
a2_.id AS id_8,
a2_.name AS name_9,
g3_.id AS id_10,
g3_.name AS name_11,
j4_.id AS id_12,
j4_.name AS name_13,
j5_.id AS id_14,
j5_.name AS name_15,
w6_.id AS id_16,
w6_.name AS name_17
FROM
job j0_
INNER JOIN company c1_ ON j0_.company_id = c1_.id
INNER JOIN activity_sector a2_ ON j0_.activity_sector_id = a2_.id
INNER JOIN geo__name g3_ ON j0_.geoname_id = g3_.id
INNER JOIN job_salary_type j4_ ON j0_.salary_type_id = j4_.id
INNER JOIN job_contract_type j5_ ON j0_.contract_type_id = j5_.id
INNER JOIN workday w6_ ON j0_.workday_id = w6_.id
WHERE
j0_.active >= CURRENT_TIMESTAMP
AND j0_.status = 1
ORDER BY
j0_.created_at DESC
执行上述查询时,我得到以下结果:
在MYSQL工作台中:0.578 sec / 0.016 sec
在Symfony探查器中:755.15 ms
问题是:此查询的持续时间是否正确?如果没有,如何提高查询速度?似乎很多。
symfony调试工具栏,如果有帮助:
键太多,请尽量减少键的数量。
Symfony速度缓慢的原因有很多。
1。服务器故障
首先,这可能是服务器故障。服务器性能可能会影响您的查询时间。
2。数据大小和延迟渲染
然后是数据大小。如下图所示,我的一个项目的查询的数据大小为50Mb(当前约2万行)。在HTML中解析50Mb可能需要一些时间,这主要是因为循环。仍然有关于此的解决方案,例如延迟渲染。
延迟渲染非常简单,您无需解析树枝中的数据,将所有数据发送到javascript变量,并在加载DOM后使用javascript解析/呈现数据。
3。查询优化
正如我在评论中写道,您可以检查以下问题,在该问题上,我解释了为什么自定义查询很重要。Are Doctrine relations affecting application performance?
在这个问题上,您将阅读该顺序的问题……实际上,这是最重要的。
虽然数据库中的静态数据通常以正确的顺序插入,动态数据(用户在网站生命期间提供的数据)很少出现这种情况]
这就是为什么在查询中使用ORDER BY
通常会加快页面呈现的速度,因为教义本身不会做额外的查询。
例如,我的一个站点在索引上显示了约700个条目。首先,这是使用findAll()
时的查询计数:
它在144毫秒内显示254个查询(253个重复项),外加39个渲染时间。接下来,使用findBy()
的第二个参数ORDER BY
,我得到以下结果:
您可以看到full query here(镜头很大)更好的是,仅在8毫秒内进行1次查询,并且渲染时间大致相同。但是,在这里,我不使用关联中的任何字段。从我要做的那一刻起,doctrine qui会做一些额外的查询,并且查询数量和时间将猛增。最后,它将回到类似findAll()
最后,这是自定义查询:
在此custom query中,查询时间从8ms变为38ms。但是,与之前的查询不同,我在查询结果中获得了更多数据,这将阻止教义进行额外的查询。同样,ORDER BY()
在此查询中很重要。没有它,我将猛增回84个查询。
4。局部]
当您执行自定义查询时,您可以加载部分对象而不是全部数据。就像您在问题中说的那样,description
字段似乎减慢了您的加载速度,使用局部函数,可以避免从表中加载某些字段,这将加快查询速度。
首先,这是您创建查询生成器的方式,而不是常规语法:
$em=$this->getEntityManager();
$qb=$em->createQueryBuilder();
以防万一,我更愿意将$em
保留为单独的变量(例如,如果我想获取某些类存储库)。
然后您可以启动部分select
。请注意,第一个select
不能包含任何关联字段:
$qb->select("partial job.{id, status, title, minimum_experience, min_salary, max_salary, zip_code, vacancies")
->from(Job::class, "job");
然后您可以添加关联:
$qb->addSelect("company")
->join("job.company", "company");
甚至在不需要所有关联数据的情况下,甚至添加部分关联:
$qb->addSelect("partial activitySector.{id}")
->join("job.activitySector", "activitySector");
$qb->addSelect("partial job.{id, company_id, activity_sector_id, status, active, contract_type_id, salary_type_id, workday_id, geoname_id, title, minimum_experience, min_salary, max_salary, zip_code, vacancies, show_salary");
5。缓存
您还可以使用各种缓存,例如Zend OPCache for PHP,您可以在此问题中找到一些建议:Why Symfony3 so slow?
还有SQL缓存Varnish。
本文汇总了我可以共享的所有内容,以减少您的加载时间。
希望它将证明是有用的,您将能够解决您的问题。