简体   繁体   中英

Is NOT IN faster than inequals in MySQL?

I'm trying to figure out if there's a more efficient way to write my stored procedure for MySQL 5.5. Essentially the stored procedure will truncate data from all my created tables except a select few. I try to achieve this by executing the below …

create procedure truncate_tables()
begin
 declare tab_name varchar(64);
 declare done tinyint unsigned default 0;

 declare table_cur cursor for select t.table_name
 from
  information_schema.schemata s
  inner join information_schema.tables t on s.schema_name = t.table_schema
 where
   s.schema_name = database() 
   and t.table_type = 'BASE TABLE'
   and t.table_name not like 'DATABASE%'
   and t.table_name != ‘my_table_1’
   and t.table_name != ‘my_table_2’
   and t.table_name != ‘my_table_3’
   …
   and t.table_name != ‘my_table_n-1’
   and t.table_name != ‘my_table_n’;

 declare continue handler for not found set done = 1;

 open table_cur;
 repeat
   fetch table_cur into tab_name;
   set @cmd = concat('truncate table ', tab_name);

   prepare stmt from @cmd;
   execute stmt;
 until done end repeat;

 close table_cur;
end

As I explore ways to make this faster, should I replace my numerous inequals clauses with a "NOT IN (list)" clause? Not sure which will execute faster in MySQL or if there are other efficiencies to be gained.

NOT IN is a clearer way to write the code and it makes the code more maintainable (easier to add new table names, easier to understand).

You are working off of system tables, which are probably not that large. You are doing a join which probably has more overhead than the where clause. And, you are using a cursor to access the data. The difference in performance is likely to be negligible for some micro-optimization on the where clause.

Go with not in .

And, if you are really concerned, test both methods and choose the one that is faster.

To answer the question in the title of your question, no, there's no difference in performance, in terms of the generated execution plan. The two forms are equivalent. (It's possible that there might be tiny bit of difference in performance in actually parsing the statement, but that's not going to be measurable.

I expect the bulk of the time will be in actually performing the individual TRUNCATE statements.


You don't need a join to the schemata table, you can reference the table_schema column in the tables table in the predicate:

SELECT t.table_name
  FROM information_schema.tables t 
 WHERE t.table_schema = DATABASE()
   AND t.table_type = 'BASE TABLE'
   AND ...

The predicate

foo NOT IN ('a','b','c')

is equivalent to

(foo != 'a' AND foo != 'b' AND foo != 'c')

There's no difference in the execution plan; in this case, the NOT IN just avoids us having to repeat the reference to foo and makes the statement easier to read, understand and maintain.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM