MySQL 不同于子查询

MySQL Distinct from subQuery

移动到:MySQL Distinct performance

基本思路:

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

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

现在通过在 table->Frequency->20 中标记,数据库应该每隔 table 检查是否有使用 Freq 20 测量的条目并更新所有 tables取决于 20.

但是:我只想在每个 table 中显示不同的值。而这个 distinct 需要 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

我真的很奇怪为什么这个 distinct 需要这么长时间。这里的所有行都有索引。 此示例仅显示一个 table 的代码。但是我需要 9 个更新 tables.

有什么方法可以加快这个过程或这个 "select distinct" 查询吗?

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

database

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

您要将 8 个 table 连接在一起,唯一的限制是产品名称必须是 "GoodProduct"product-table 与 product_name 相对 chip 连接在一起,因此您应该检查这些 name/product_name 列上是否有索引.根据 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")

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

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

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)