简体   繁体   English

通过5个连接提高查询性能

[英]Improve query performance with 5 join

using a local java program I have access to a database on a vps whose tables involved have an average of about 1,500 records. 使用本地Java程序,我可以访问vps上的数据库,该表所涉及的表平均约有1,500条记录。

Unfortunately, despite the records are not many, I have performance issues around 10sec for the extraction. 不幸的是,尽管记录并不多,但提取时却出现了大约10秒的性能问题。

The query is as follows: 查询如下:

SELECT  DISTINCT P.advanced_stock_management,
        PA.id_product, PA.reference, PL.name,
        round(P.wholesale_price,2),
        round((P.price + P.price * 22 / 100), 2),
        round(SP.reduction,2),
        SA.quantity, PQ.is_true
    FROM  db.ps_product AS P
    INNER JOIN  db.ps_product_attribute AS PA
          ON P.id_product=PA.id_product
    INNER JOIN  db.ps_product_lang AS PL 
          ON PA.id_product=PL.id_product
    INNER JOIN  db.ps_stock_available AS SA
          ON SA.id_product_attribute=PA.id_product_attribute
    LEFT OUTER JOIN  db.ps_product_quantity_real AS PQ
          ON PA.id_product=PQ.id_product
         AND  PA.reference=PQ.reference
    LEFT OUTER JOIN  db.ps_specific_price AS SP
          ON PA.id_product=SP.id_product
    WHERE  P.active = 1;

How can I improve structure of the query and increase performance? 如何改善查询的结构并提高性能?

Thanks in advance. 提前致谢。

You should have proper indexes on the following columns: 您应该在以下列上使用适当的索引:

table_name (column_name)
ps_product (id_product)
ps_product_attribute (id_product)
ps_product_attribute (reference) 
ps_product_attribute (id_product_attribute)
ps_product_lang (id_product)
ps_stock_available (id_product_attribute)
ps_product_quantity_real (id_product)
ps_product_quantity_real (reference)
ps_specific_price (id_product)

By rewrite the query with a proper indentation: 通过使用适当的缩进重写查询:

SELECT DISTINCT 
    product.advanced_stock_management, 
    attribute.id_product, 
    attribute.reference, 
    lang.name, 
    round(product.wholesale_price,2), 
    round((product.price + product.price * 22 / 100),2), 
    round(price.reduction,2), 
    availablity.quantity, 
    quantity.is_true
FROM db.ps_product AS product
    INNER JOIN db.ps_product_attribute AS attribute 
        ON product.id_product = attribute.id_product
            INNER JOIN db.ps_product_lang AS lang 
                ON lang.id_product = attribute.id_product
            INNER JOIN db.ps_stock_available AS availablity 
                ON availablity.id_product_attribute = attribute.id_product_attribute
            LEFT OUTER JOIN db.ps_product_quantity_real AS quantity 
                ON attribute.id_product = quantity.id_product 
                AND attribute.reference = quantity.reference
            LEFT OUTER JOIN db.ps_specific_price AS price 
                ON price.id_product = attribute.id_product
WHERE product.active = 1;

We can see that the central table is in fact ps_product_attribute . 我们可以看到中央表实际上是ps_product_attribute Let's make it the start of the query: 让我们将其作为查询的开始:

SELECT DISTINCT 
    product.advanced_stock_management, 
    attribute.id_product, 
    attribute.reference, 
    lang.name, 
    round(product.wholesale_price,2), 
    round((product.price + product.price * 22 / 100),2), 
    round(price.reduction,2), 
    availablity.quantity, 
    quantity.is_true
FROM db.ps_product_attribute AS attribute
    INNER JOIN db.ps_product AS product
        ON attribute.id_product = product.id_product
    INNER JOIN db.ps_product_lang AS lang 
        ON attribute.id_product = lang.id_product 
    INNER JOIN db.ps_stock_available AS availablity 
        ON attribute.id_product_attribute = availablity.id_product_attribute
    LEFT OUTER JOIN db.ps_product_quantity_real AS quantity 
        ON attribute.id_product = quantity.id_product 
        AND attribute.reference = quantity.reference
    LEFT OUTER JOIN db.ps_specific_price AS price 
        ON attribute.id_product = price.id_product
WHERE product.active = 1;

The query looks very good now. 现在查询看起来非常好。
Do you have indexes on every field in this query? 在此查询的每个字段上都有索引吗? If not, you should! 如果没有,您应该!

ALTER TABLE `ps_product_attribute` ADD INDEX `id_product` (`id_product`)
ALTER TABLE `ps_product_attribute` ADD INDEX `reference` (`reference`)
ALTER TABLE `ps_product` ADD INDEX `id_product` (`id_product`)
ALTER TABLE `ps_product_lang` ADD INDEX `id_product` (`id_product`)
ALTER TABLE `ps_stock_available` ADD INDEX `id_product_attribute` (`id_product_attribute`)
ALTER TABLE `ps_product_quantity_real` ADD INDEX `id_product` (`id_product`)
ALTER TABLE `ps_product_quantity_real` ADD INDEX `reference` (`reference`)
ALTER TABLE `ps_specific_price` ADD INDEX `id_product` (`id_product`)

With this database size, the query should runs under 1 second. 使用此数据库大小,查询应在1秒内运行。

You've two options 你有两个选择

  • Pre-fetch 1500 records in memory and then join using record matching ( no database ). 在内存中预取1500条记录,然后使用记录匹配( 无数据库 )进行联接。 Pre-fetch provides speed and removed network latency in accessing records from Database but ya record matching will be slow and tiresome. 在从数据库访问记录时,预取提供了速度并消除了网络延迟,但是Ya记录匹配将非常缓慢且令人厌烦。

  • Use apache spark with local cluster ( bigdata joins ). 在本地集群中使用apache spark( bigdata joins )。 I've personally executed 1million * 2 join under 9ms. 我已经在9ms内亲自执行了100万* 2次加入。 This must be implemented using in-memory RDD only. 必须仅使用内存内RDD来实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM