簡體   English   中英

從MariaDB遷移到MySQL后,EXPLAIN顯示“ DEPENDENT SUBQUERY”並且非常慢

[英]EXPLAIN Shows “DEPENDENT SUBQUERY” and very slow after migrating from MariaDB to MySQL

我正在使用mysqldump方法使用Mysql 5.7從舊的MariaDB 10.0數據庫遷移到新的Google Cloud Sql。 遷移之后,我得到了有關WHERE EXISTS語句的一些非常慢的查詢。

我試圖在我的舊數據庫和新數據庫上解釋我的查詢,它解釋了不同的結果。 由於它使用轉儲,因此我假設表索引沒有變化。 這是我想運行的查詢

SELECT * FROM detitem
    where exists (select 1 from detlayanan
                    where detitem.iddetlayanan = detlayanan.id
                      and detlayanan.layanan_idlayanan='LYN15176176101503')

舊數據庫的解釋

+------+-------------+------------+------+------------------------------------+----------------------------+---------+--------------------------------+-------+--------------------------+
| id   | select_type | table      | type | possible_keys                      | key                        | key_len | ref                            | rows  | Extra                    |
+------+-------------+------------+------+------------------------------------+----------------------------+---------+--------------------------------+-------+--------------------------+
|    1 | PRIMARY     | detlayanan | ref  | PRIMARY,fk_detlayanan_layanan1_idx | fk_detlayanan_layanan1_idx | 22      | const                          | 11030 | Using where; Using index |
|    1 | PRIMARY     | detitem    | ref  | FK_detitem_detlayanan              | FK_detitem_detlayanan      | 52      | citridia_sinadme.detlayanan.id |     1 |                          |
+------+-------------+------------+------+------------------------------------+----------------------------+---------+--------------------------------+-------+--------------------------+

和來自新數據庫的解釋

+----+--------------------+------------+------------+--------+------------------------------------+---------+---------+---------------------------------------+---------+----------+-------------+
| id | select_type        | table      | partitions | type   | possible_keys                      | key     | key_len | ref                                   | rows    | filtered | Extra       |
+----+--------------------+------------+------------+--------+------------------------------------+---------+---------+---------------------------------------+---------+----------+-------------+
|  1 | PRIMARY            | detitem    | NULL       | ALL    | NULL                               | NULL    | NULL    | NULL                                  | 2079094 |   100.00 | Using where |
|  2 | DEPENDENT SUBQUERY | detlayanan | NULL       | eq_ref | PRIMARY,fk_detlayanan_layanan1_idx | PRIMARY | 52      | citridia_sinadme.detitem.iddetlayanan |       1 |     5.00 | Using where |
+----+--------------------+------------+------------+--------+------------------------------------+---------+---------+---------------------------------------+---------+----------+-------------+

即使存在索引,新程序也會執行全表掃描。 我在這里想念什么嗎?

這是“ detlayanan”表

CREATE TABLE `detlayanan` (
  `transaksi_idtransaksi` varchar(40) NOT NULL,
  `layanan_idlayanan` varchar(20) NOT NULL,
  `nama_layanan` varchar(255) DEFAULT NULL,
  `jumlah_beli` float DEFAULT NULL,
  `id` varchar(50) NOT NULL,
  `harga` decimal(20,2) DEFAULT '0.00',
  `hargatotal` decimal(20,2) DEFAULT '0.00',
  `luas_p` double(255,2) DEFAULT '0.00',
  `luas_l` double(255,2) DEFAULT '0.00',
  `luas_q` double(255,2) DEFAULT '0.00',
  `keterangan` varchar(255) DEFAULT '',
  `iddeposit` varchar(255) DEFAULT NULL,
  `posisi` tinyint(4) DEFAULT '1',
  `idworkshop` varchar(60) DEFAULT NULL,
  `is_wsot` tinyint(4) DEFAULT '0',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
  `total_bersih` varchar(20) DEFAULT '0',
  `total_min_order` decimal(20,2) DEFAULT '0.00',
  `kondisi_barang` text,
  PRIMARY KEY (`id`),
  KEY `fk_detlayanan_layanan1_idx` (`layanan_idlayanan`),
  KEY `fk_detlayanan_deposit` (`iddeposit`),
  KEY `transaksi_idtransaksi` (`transaksi_idtransaksi`),
  CONSTRAINT `detlayanan_ibfk_1` FOREIGN KEY (`transaksi_idtransaksi`) REFERENCES `transaksi` (`idtransaksi`),
  CONSTRAINT `fk_detlayanan_layanan1` FOREIGN KEY (`layanan_idlayanan`) REFERENCES `layanan` (`idlayanan`) ON DELETE NO ACTION ON UPDATE NO ACTION
)

這是“細節”表

CREATE TABLE `detitem` (
  `item_iditem` varchar(20) NOT NULL,
  `layanan_idlayanan` varchar(255) NOT NULL,
  `jumlah_item` int(255) DEFAULT NULL,
  `transaksi_idtransaksi` varchar(255) NOT NULL,
  `id` varchar(50) NOT NULL,
  `iddetlayanan` varchar(50) NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
  `hapus` tinyint(4) DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `FK_detitem_item` (`item_iditem`),
  KEY `FK_detitem_layanan` (`layanan_idlayanan`),
  KEY `FK_detitem_transaksi` (`transaksi_idtransaksi`),
  KEY `FK_detitem_detlayanan` (`iddetlayanan`),
  CONSTRAINT `FK_detitem_detlayanan` FOREIGN KEY (`iddetlayanan`) REFERENCES `detlayanan` (`id`),
  CONSTRAINT `FK_detitem_item` FOREIGN KEY (`item_iditem`) REFERENCES `item` (`iditem`),
  CONSTRAINT `FK_detitem_layanan` FOREIGN KEY (`layanan_idlayanan`) REFERENCES `layanan` (`idlayanan`),
  CONSTRAINT `FK_detitem_transaksi` FOREIGN KEY (`transaksi_idtransaksi`) REFERENCES `transaksi` (`idtransaksi`)
)

我希望解釋的“行數”保持很小,在舊的DB中,即使在另一個表中,“行數”也保持在非常低的水平。 但在新的數據庫中,它最多可以顯示一百萬。

UPDATE

經過一些研究,實際上我必須在where語句中顯式添加一些索引列以伴隨EXISTS語句。 因此查詢將像這樣

SELECT  * FROM  detitem WHERE
    <indexed column> in (<some id's>)
    AND EXISTS ( SELECT 1 FROM detlayanan WHERE detitem.iddetlayanan = 
    detlayanan.id AND detlayanan.layanan_idlayanan = 'LYN15176176101503' )

顯然,MySQL對目標表進行了全面掃描以檢查子查詢值是否存在,當聲明了一些索引列時,sql不需要這樣做。 在MySQL中也發現了這種情況。

一些參考: https : //mariadb.com/kb/en/library/exists-to-in-optimization/

這看起來像MariaDB的Optimizer比MySQL領先一兩個步驟的情況。

看看這是否運作良好:

SELECT  i.*
    FROM ( SELECT  id
            FROM  detlayanan
            WHERE  layanan_idlayanan = 'LYN15176176101503' 
         ) AS x
    JOIN  detitem AS i  ON x.id = i.iddetlayanan 

認為它將在兩台服務器上都能很好地工作。

更簡單了:

SELECT  i.*
    FROM  detlayanan AS lay
    JOIN  detitem AS i  ON lay.id = i.iddetlayanan 
    WHERE  lay.layanan_idlayanan = 'LYN15176176101503' 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM