【问题标题】:MySQL Distinct from subQueryMySQL 与 subQuery 不同
【发布时间】:2020-05-03 01:35:43
【问题描述】:

移至:MySQL Distinct performance

基本思路:

1) 我有一个包含大量数据的 Mysql 服务器: 9 个表都以或多或少的线性方式与外键链接。

2) 使用 GUI 我想提取一些结果: 显示了这 9 个表,每个表只有一个变量。让我们说:

  • 表 1:频率:20,40,80,100
  • 表2:波长:300,400,500,600
  • 表 3:....

现在通过在 table->Frequency->20 中标记,数据库应该检查每隔一个表是否有使用 Freq 20 测量的条目,并根据 20 更新所有表。

但是:我只想在每个表中显示不同的值。而这个不同需要 17 秒,这对于 GUI 来说是非常糟糕的等待。

示例代码:

SELECT wafer.ID
FROM product
  JOIN chip ON chip.product_name=product.name
  JOIN wafer ON wafer.ID = chip.wafer_ID
  JOIN lot ON lot.ID = wafer.lot_ID
  JOIN ROI ON ROI.ID_string = chip.ROI_ID
  JOIN result ON result.chip_ID = chip.ID_string
  JOIN setup ON setup.ID_md5 = result.setup_ID 
  JOIN dataset ON dataset.ID_md5 = result.dataset_ID
WHERE product.name IN ("GoodProduct")

持续时间:0.34 秒 获取:17 秒(1.5e6 行)

解释:

id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
1   SIMPLE  product     const   PRIMARY,name_UNIQUE PRIMARY 137 const   1   100.00  Using index
1   SIMPLE  dataset     index   PRIMARY,ID_UNIQUE   ID_UNIQUE   137     501 100.00  Using index
1   SIMPLE  result      ref dataset-result_idx,chip_ID_idx,setupID  dataset-result_idx  137 databaseName.dataset.ID_md5 159 100.00  
1   SIMPLE  setup       eq_ref  PRIMARY PRIMARY 137 databaseName.result.setup_ID    1   100.00  Using index
1   SIMPLE  chip        eq_ref  PRIMARY,ID_UNIQUE,Chip_UNIQUE,product_name_idx,ROI_ID   PRIMARY 452 databaseName.result.chip_ID 1   49.99   Using where
1   SIMPLE  ROI     eq_ref  PRIMARY,ID_UNIQUE   PRIMARY 302 databaseName.chip.ROI_ID    1   100.00  Using index
1   SIMPLE  wafer       eq_ref  PRIMARY,waferID_UNIQUE,number   PRIMARY 62  databaseName.chip.wafer_ID  1   100.00  
1   SIMPLE  lot     eq_ref  PRIMARY,lotnumber_UNIQUE    PRIMARY 62  databaseName.wafer.lot_ID   1   100.00  Using index

SELECT distinct wafer.ID {...same code as before}

持续时间:23 秒 获取:0.000 秒(54 行)

解释:

id, select_type, table, partitions, type, possible_keys, key, key_len, ref, rows, filtered, Extra
1   SIMPLE  product     const   PRIMARY,name_UNIQUE PRIMARY 137 const   1   100.00  Using index; Using temporary
1   SIMPLE  dataset     index   PRIMARY,ID_UNIQUE   ID_UNIQUE   137     501 100.00  Using index
1   SIMPLE  result      ref dataset-result_idx,chip_ID_idx,setupID  dataset-result_idx  137 databaseName.dataset.ID_md5 159 100.00  
1   SIMPLE  setup       eq_ref  PRIMARY PRIMARY 137 databaseName.result.setup_ID    1   100.00  Using index
1   SIMPLE  chip        eq_ref  PRIMARY,ID_UNIQUE,Chip_UNIQUE,product_name_idx,ROI_ID   PRIMARY 452 databaseName.result.chip_ID 1   49.99   Using where
1   SIMPLE  ROI     eq_ref  PRIMARY,ID_UNIQUE   PRIMARY 302 databaseName.chip.ROI_ID    1   100.00  Using index
1   SIMPLE  wafer       eq_ref  PRIMARY,waferID_UNIQUE,number   PRIMARY 62  databaseName.chip.wafer_ID  1   100.00  
1   SIMPLE  lot     eq_ref  PRIMARY,lotnumber_UNIQUE    PRIMARY 62  databaseName.wafer.lot_ID   1   100.00  Using index; Distinct

我真的很想知道为什么这种不同需要这么长时间。这里的所有行都有索引。 此示例仅显示一个表的代码。但我需要 9 个更新表。

有什么方法可以加快这个过程或这个“选择不同”的查询?

顺便说一句:我真的无法理解解释。如果有很大的提示我不会看到它......

database

【问题讨论】:

  • 是否需要包含lot?请提供SHOW CREATE TABLE,至少对于datasetresult

标签: mysql join optimization distinct explain


【解决方案1】:

在询问查询性能问题时,您应该显示表结构和索引,以便更容易提供帮助。

您将 8 个表连接在一起,唯一的限制是产品名称必须是 "GoodProduct"product-table 与 chipproduct_name 连接,因此您应该检查您是否在这些 name/product_name-columns 上有索引。根据ROIresult 中的行数,您可能需要对它们进行复合索引。

您的查询格式有点复杂且难以阅读。你通过使用格式来简化事情:

SELECT wafer.ID
FROM product
  JOIN chip ON chip.product_name=product.name
  JOIN wafer ON wafer.ID = chip.wafer_ID
  JOIN lot ON lot.ID = wafer.lot_ID
  JOIN ROI ON ROI.ID_string = chip.ROI_ID
  JOIN result ON result.chip_ID = chip.ID_string
  JOIN setup ON setup.ID_md5 = result.setup_ID 
  JOIN dataset ON dataset.ID_md5 = result.dataset_ID
WHERE product.name IN ("GoodProduct")

请注意,表 lotROIresultsetupdataset 出现在查询中只是因为每个表上都需要有一行与 "GoodProduct" 匹配。如果这不是必需的,您可以只使用productchipwafer-tables 进行查询,性能会好很多。

【讨论】:

  • 感谢您的回答!你可能不明白我的意图(可能是因为我的描述不好):问题不是选择,而是不同。我需要加入所有这些表,因为它们通过数据库中的外键以这种方式链接。或者我可以只加入 2 个没有直接链接的表吗?
  • @Langer 您可以随时改进问题以明确您的意图。了解查询性能是主要问题。
  • 连接的减少意味着我的 GUI 总是必须找出我需要哪些连接,这意味着 GUI 中需要更多的编码,或者 MySQL 中有更复杂的方法吗?
  • @Langer 不确定您的 GUI 与您的查询有什么关系(除了调用它)。您只需要包括那些需要的表。您不需要仅仅因为有外键就包括所有这些。
  • GUI 不是这个问题的一部分,但表明了我的意图。我想通过单击一个产品来更新所有 9 个表。这意味着当我希望显示所有 result.tpName 时,我需要通过 JOIN ON 链接所有表......或者我可以说一些类似的想法: JOIN result.tpName with product.name where prduct.name = 'good product'和 setup.frequency=20 ?
【解决方案2】:

这些表中的大多数对查询都没有任何证明。删除lotdataset,也许还有更多。 OTOH,他们可能提供的一件事是,例如,该项目是否有“批次”。也就是说,这不会给你想要的答案吗?

SELECT  DISTINCT wafer.ID
    FROM  product
    JOIN  chip  ON chip.product_name = product.name
    JOIN  wafer  ON wafer.ID = chip.wafer_ID
    WHERE  product.name IN ("GoodProduct")

如果您还没有这些索引,它们可能会有所帮助:

product:  (name)
result:  (dataset_ID, setup_ID, chip_ID)
dataset:  (ID_md5)
setup:  (ID_md5)
chip:  (ID_string, ROI_ID, wafer_ID, product_name)
ROI:  (ID_string)
wafer:  (lot_ID, ID)

【讨论】:

    猜你喜欢
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    • 2016-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多