当前位置:网站首页>Or in SQL, what scenarios will lead to full table scanning

Or in SQL, what scenarios will lead to full table scanning

2022-07-07 10:05:00 knight_ hf

For some time, I have been thinking of using or Will cause a full table scan , The reason is probably 2010 In, I wrote a stored procedure for data processing , Because when associating several large tables or Improper use of , As a result, the query of data is very slow . After that experience , Has been to or Use in awe , Every time I use or I think it will lead to full table scanning . At that time, in order to solve the problem or Performance problems of , The plan adopted is union all To replace or. But this also brings a problem ——sql The brevity of .

After many years , Recently, I have been hearing DBA Many projects are said in the company because or The use of leads to the decline of query performance , So I began to ask myself ,or Will it cause full table scanning if it is really used ? that or What is the value of this grammar ?

With these questions , I think it is necessary to test a question for many years ( I still lack the spirit to study the technical details , It took me so long to decide to test myself , It's a shame .)


Test database :mysql5.7.10 

Testing process : 

new table

<span style="font-size:14px;"><span style="font-size:12px;">SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `t_in_or_union_test`
-- ----------------------------
DROP TABLE IF EXISTS `t_in_or_union_test`;
CREATE TABLE `t_in_or_union_test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `text_1` varchar(10) DEFAULT NULL,
  `text_2` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_1` (`text_1`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;</span></span>
<span style="font-size:14px;"><span style="font-size:12px;">
</span></span>
<span style="font-size:14px;"><span style="font-size:12px;">--  initialization 100W Data 
begin
declare i int;
set i=0;
while i<1000000 do
insert into t_in_or_union_test(text_1,text_2) values(i+1,i+2);
set i=i+1;
end while;
end</span></span>

After initializing the data , Execute the following script , After parsing, it is found that the index will be used . And remove explain Direct execution sql Query will find that basically every query execution is very fast, and the query results .

<span style="font-size:14px;"><span style="font-size:12px;">explain
select * from t_in_or_union_test
where text_1 ='100'
or text_1 = '101'
or text_1 = '102'
or text_1 = '103'
or text_1 = '104'
or text_1 = '105'
or text_1 = '106'
or text_1 = '107'
or text_1 = '108'
or text_1 = '109'
or text_1 = '110'</span></span>
Although or, But it did not lead to the expected full table scan .

Create a similar table to test :

<span style="font-size:14px;"><span style="font-size:12px;">SET NAMES utf8;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
--  Table structure for `t_in_or_union_test_2`
-- ----------------------------
DROP TABLE IF EXISTS `t_in_or_union_test_2`;
CREATE TABLE `t_in_or_union_test_2` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `text_1` varchar(10) DEFAULT NULL,
  `text_2` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_1` (`text_1`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;</span></span>

Also use scripts to initialize test data

<span style="font-size:14px;"><span style="font-size:12px;">begin
declare i int;
set i=0;
while i<100000 do
insert into t_in_or_union_test_2(text_1,text_2) values(i+1,i+2);
set i=i+1;
end while;
end</span></span>

Then execute the following two paragraphs sql:

<span style="font-size:14px;"><span style="font-size:12px;">EXPLAIN
select * from t_in_or_union_test_2 A
left join t_in_or_union_test B on A.text_1 = B.text_1
and B.text_1 = '100'
or B.text_1 = '101'

select * from t_in_or_union_test_2 A
left join t_in_or_union_test B on A.text_1 = B.text_1
and B.text_1 = '100'
or B.text_2 = '101'</span></span>

from sql The analytic result of , The first session sql Can walk the index , But the second paragraph doesn't go through the index , Get rid of explain perform sql Inquire about , The result is that the second paragraph needs to be executed for a long time .

From the above execution results , Two different fields are used or It seems to have led to a full table scan , Although both fields are indexed .

Write three more paragraphs to query directly through the primary key sql

<span style="font-size:14px;"><span style="font-size:12px;">explain
select * from t_in_or_union_test
where 1=1 or id = 100056 or id = 10005

explain
select * from t_in_or_union_test
where 1=1 and (id = 100056 or id = 10005)

explain
select * from t_in_or_union_test
where id = 100056 or id = 10005</span></span>

Separately , Find the first paragraph sql No primary key index , second 、 Three paragraphs will go through the primary key index .

Through the above several small experiments , Basically, it can be verified that it is used between two identical fields or Will not cause a full table scan , Only when there is an impassable field, it can be self built and used or It will cause full table scanning .

Personally, I think an index should be located to 1 Data , An index should be located at 100 Data , The query optimizer cannot meet this requirement at the same time , Only full table scanning can be used to query data .

Simply do some verification , Recognize some points that were not confirmed before , About or Use , If you have different understandings , Communicate more .


原网站

版权声明
本文为[knight_ hf]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202130623569711.html