Rumah >pangkalan data >tutorial mysql >Analisis masalah yang memadam dalam subquery tidak pergi ke indeks dalam mysql

Analisis masalah yang memadam dalam subquery tidak pergi ke indeks dalam mysql

WBOY
WBOYke hadapan
2022-09-08 17:46:342859semak imbas

Pembelajaran yang disyorkan: tutorial video mysql

Sebelum artikel dimulakan, izinkan saya bertanyakan soalan kepada anda: padam masuk subquery , adakah ia akan diindeks? Tanggapan pertama ramai rakan kongsi ialah mereka tahu cara mengindeks. Baru-baru ini kami menghadapi masalah pengeluaran yang berkaitan dengannya. Artikel ini akan membincangkan isu ini dengan semua orang dan melampirkan pelan pengoptimuman.

Penghasilan semula masalah

Versi MySQL ialah

Andaikan terdapat dua jadual 5.7 dan account struktur adalah seperti berikut: old_account

adalah seperti berikut:
CREATE TABLE `old_account` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
  `name` varchar(255) DEFAULT NULL COMMENT '账户名',
  `balance` int(11) DEFAULT NULL COMMENT '余额',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT='老的账户表';
CREATE TABLE `account` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
  `name` varchar(255) DEFAULT NULL COMMENT '账户名',
  `balance` int(11) DEFAULT NULL COMMENT '余额',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `update_time` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8 ROW_FORMAT=REDUNDANT COMMENT='账户表';

Mari jelaskan rancangan pelaksanaan dan dapatkan hasil daripada
delete from account where name in (select name from old_account);

Boleh didapati bahawa: mula-mula

imbas seluruh jadual

explain, dan kemudian laksanakan subkueri baris demi baris untuk menentukan sama ada syarat dipenuhi, jelas sekali, pelan pelaksanaan ini tidak memenuhi jangkaan kami, kerana tidak menggunakan indeks . accountTetapi jika anda menggantikan dengan

, indeks akan hilang. Seperti berikut:

deleteselect

Mengapakah subkueri pilih dalam

melalui indeks, tetapi pemadaman dalam subkueri tidak melalui indeks?

Analisis Sebab

Apakah perbezaan antara

pernyataan subkueri dan

pernyataan subkueri? select indelete in Mari laksanakan SQL berikut untuk melihat

explain select * from account where name in (select name from old_account);
show WARNINGS;
tunjukkan AMARAN

Anda boleh melihat sql yang dilaksanakan akhir selepas pengoptimuman

Keputusan adalah seperti berikut:

pilih `test2`.`account`.`id` AS `id`,`test2`.`account`.`name` AS `name`,` test2`.` account`.`balance` AS `balance`,`test2`.`account`.`create_time` AS `create_time`,`test2`.`account`.`update_time` AS `update_time` daripada `test2` .`akaun`
separuh sertai (`test2`.`old_account`)

di mana (`test2`.`account`.`name` = `test2`.`old_account`.`name`)

Dapat didapati bahawa semasa pelaksanaan sebenar, MySQL mengoptimumkan
pilih dalam subkueri

dan menukar subkueri kepada kaedah gabungan, supaya indeks boleh digunakan. Tetapi malangnya, MySQL tidak mengoptimumkannya untuk padam dalam subquery . Pelan pengoptimuman

Jadi bagaimana untuk mengoptimumkan masalah ini? Melalui analisis di atas, jelas sekali pemadaman dalam subkueri boleh ditukar kepada kaedah

sertai

. Selepas kita menukar kepada kaedah gabungan, mari kita jelaskan sekali lagi:

Kita dapati bahawa kaedah gabungan ialah

yang boleh diindeks

, yang merupakan kaedah yang sempurna penyelesaian menyelesaikan masalah ini. Malah, untuk mengemas kini atau memadam kenyataan subquery,

Tapak web rasmi MySQL

juga mengesyorkan kaedah sertai untuk mengoptimumkan

Malah, Menambah alias pada jadual juga boleh menyelesaikan masalah ini, seperti berikut:

explain delete a from account as a where a.name in (select name from old_account)

Mengapa menambah alias boleh mendayakan pengindeksan?

apa

? Mengapakah mungkin untuk menambah alias, memadam dalam subquery, dan menggunakan indeks sekali lagi? Mari kita lihat kembali rancangan pelaksanaan explain, dan kita dapat melihat bahawa dalam lajur Tambahan, terdapat

LooseScan

.

Apakah itu LooseScan?

Sebenarnya, ia adalah strategi, strategi pelaksanaan subkueri separuh sertai. Oleh kerana subkueri ditukar untuk bergabung, pemadaman dalam subkueri boleh diindeks

menambah alias

akan menggunakan strategi LooseScan, dan pada dasarnya strategi LooseScan ialah Ia; ialah strategi pelaksanaan subkueri separuh sertai . Oleh itu, menambah alias membenarkan pemadaman dalam subquery diindeks!

Pembelajaran yang disyorkan:

tutorial video mysql

Atas ialah kandungan terperinci Analisis masalah yang memadam dalam subquery tidak pergi ke indeks dalam mysql. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:jb51.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam