如何通过多联接获取大量数据

时间:2018-08-08 07:20:05

标签: php mysql sql

我必须从20个左右的表中获取超过20k的记录。 我正在使用Datatables jQuery插件进行服务器端分页。每次我重新加载页面或跳到另一页面时,都花了25秒,这太奇怪了。这是我的查询:

SELECT 
    * 
FROM 
    `bp` 
left join 
    pdbp on bp.id = pdbp.bp_id 
left join 
    cities on pdbp.city = cities.CityId 
left join 
    regions on pdbp.region = regions.RegionId 
left join 
    countries on pdbp.country = countries.CountryId  
left join (
     SELECT 
         bid, 
         GROUP_CONCAT(subc_name SEPARATOR ', ') as cat 
     FROM 
         sub_categories sc 
     left join 
         `bp_categories` bc on sc.subc_cod = bc.subc_cod group by bid
     ) categories on bp.id = categories.bid 
left join (
     SELECT 
         bid as mbid, 
         GROUP_CONCAT(material SEPARATOR ', ') as mat 
     FROM 
         product_material pm 
     left join 
         `bp_materials` bm on pm.material_cod = bm.mat_cod group by bid 
) materials on bp.id = materials.mbid
left join (
    SELECT 
        bid as cbid, 
        GROUP_CONCAT(description SEPARATOR ', ') as crts from cert ct 
    left join 
        `bp_certificate` bct on ct.id = bct.cid group by cbid
    ) certificate on bp.id = certificate.cbid  

我真的需要加快速度,这很消耗我。任何帮助将不胜感激

3 个答案:

答案 0 :(得分:1)

是的,有很多方法

  • 用户服务器端使用数据表进行分页并获取10到20条记录

(如果已禁用),因为这只会减少要显示的数据量。除此之外,您用于加载数据的方法通常会对性能产生最大的影响。

Client-side processing - DOM sourced data: ~5'000 rows. Speed options: orderClasses.

Client-side processing - Ajax sourced data (ajax): ~50'000 rows. Speed options: deferRender

Server-side processing (serverSide): millions of rows.

答案 1 :(得分:1)

有几件事会影响查询的性能。

例如,我相信如果您正在使用DataTables插件,则必须确切知道要输出的字段。

  • 将适当的字段字段添加到SELECT而不是*
  • 考虑尽可能使用内部联接
  • 使用限制和偏移量从后端进行分页
  • 缓存结果...

答案 2 :(得分:0)

(1)使用视图表。

CREATE 
    VIEW `sample_view` 
    AS
(
SELECT * FROM `bp` LEFT JOIN pdbp ON bp.id = pdbp.bp_id 
LEFT JOIN cities ON pdbp.city = cities.CityId 
LEFT JOIN regions ON pdbp.region = regions.RegionId 
LEFT JOIN countries ON pdbp.country = countries.CountryId  
LEFT JOIN(SELECT bid, GROUP_CONCAT(subc_name SEPARATOR ', ') AS cat FROM sub_categories sc 
LEFT JOIN `bp_categories` bc ON sc.subc_cod = bc.subc_cod GROUP BY bid) categories ON bp.id = categories.bid 
LEFT JOIN (SELECT bid AS mbid, GROUP_CONCAT(material SEPARATOR ', ') AS mat FROM product_material pm 
LEFT JOIN `bp_materials` bm ON pm.material_cod = bm.mat_cod GROUP BY bid ) materials ON bp.id = materials.mbid
LEFT JOIN (SELECT bid AS cbid, GROUP_CONCAT(description SEPARATOR ', ') AS crts FROM cert ct 
LEFT JOIN `bp_certificate` bct ON ct.id = bct.cid GROUP BY cbid ) certificate ON bp.id = certificate.cbid  
);

尝试在自己身边跑。 然后获取分页限制的视图表。至于前端,执行时间是有限的,超过1000条记录将耗尽内存。

select * from sample_view limit 0, 20 

(2)避免在SELECT子句中使用不必要的列。 在SELECT子句中指定列,而不要使用SELECT *。不必要的列会给数据库增加额外的负担,这不仅会减慢单个SQL的速度,还会减慢整个系统的速度。

(3)嵌套查询会降低性能。尝试将所有嵌套查询直接加入主sql查询。您没有告诉我们您的数据库图,所以我不能为您提供sql语句。

(4)为JOIN,WHERE,ORDER BY和GROUP BY子句中的所有谓词建立索引。在很大程度上依赖于索引以提高SQL性能和可伸缩性。 使用

SELECT EXPLAIN

优化查询。检查此链接以了解解释功能

https://www.sitepoint.com/using-explain-to-write-better-mysql-queries/

(5)如果需要排序的结果集,则SQL中必须使用ORDER BY子句。 请注意添加ORDER BY子句对性能的影响,因为数据库需要对结果集进行排序,从而导致SQL执行中最昂贵的操作之一。