Mysql数据库中怎样快速查询符合条件的记录是否存在

时间:2021-07-16 07:33:20
例如我想知道table1里是否有city='Beijing'的记录,该怎么写查询语句呢? 
我知道可以写 
select count(*) from table1 where city='Beijing'然后就可以看到有多少条记录了; 
或者可以写 
select * from table1 where city='Beijing'然后可以通过看返回的记录集是否为空来判断是否存在符合条件的记录。 

可是现在的问题是,这个表会很大,例如几十万条记录甚至更多;city='Beijing'的记录也会有很多。通过上面的方法都会需要扫描整个表来得到结果,开销大,而我仅仅只是想知道是否存在city='Beijing'的记录而已,犯不着搞这样大的开销。 

或者有人会回答这样的: 
select * from table1 where city='Beijing' limit 1 
这样强制让查询只返回一条记录。 
可是这样也不行,Mysql还是会扫描整个表,因为它好像还会隐含的根据什么东西来进行排序,然后返回排序后的第一个记录。反正是,像上面那样写,用explain分析结果表明Mysql还是会扫描整个表的。 

怎么办?求强人指教啊!说明一句:使用的数据库是Mysql,但是凡是能解决类似问题的方法都好呀!

12 个解决方案

#1


你给字段city加上索引不就行了。

#2


同意楼上.

#3


这样的索引会指向很多记录的。这样的索引不会带来其他问题吗?

#4


所以会指向很多记录,但是你返回的少,就不会进行全表扫描了。

#5


但是建立索引之后还是会扫描大量的记录,有几万条。没见提高效率。例如一百万条记录中,只有三个不同的city,那平均下来建立索引都还是得扫描几十万条。
难道像这样的情形只能从其他方面考虑了吗?例如分表或者其他的?单纯从sql查询方面没有好办法了?

#6


我给你举个例子,补一下你的误区。

/*DDL Information For - test.song*/
-----------------------------------

Table   Create Table                                                                            
------  ----------------------------------------------------------------------------------------
song    CREATE TABLE `song` (                                                                   
          `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Autoincreament element',                
          `name` char(200) DEFAULT NULL,                                                        
          `datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  
          `rank` int(11) NOT NULL,                                                              
          PRIMARY KEY (`id`),                                                                   
          KEY `k_name` (`name`)                                                                 
        ) ENGINE=MyISAM AUTO_INCREMENT=8102001 DEFAULT CHARSET=gbk        

select count(*) from song;
explain select count(1) from song where `name` = 't1';
count(*) 
8102000 
query result(1 records)
id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE song ref k_name k_name 401 const 2 Using where; Using index 

我这个里面只是扫描了两行而已,虽然表有八百多行。

#7


#8


我按照6楼的建立了一个一样的表,弄了几条记录进去,例如name为aaa的记录有5条,其他记录有4条。
可是用explain还是显示要扫描4个记录啊,并不是就能够省下很多了。
mysql> explain select count(1) from song where name='aaa';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | song  | ref  | k_name        | k_name | 401     | const |    4 | Using where; Using index | 
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+

那么name为aaa的记录如果有10万条,还不是得扫描99999条记录?

难道跟mysql版本有关系?我的是5.0.27版本的。

#9


LZ,如果你的aaa记录非常多的话,这个就不能单纯从SQL语句方面优化了。

#10


select 1 from table1 where city= 'Beijing '

#11


看来单纯从SQL语句方面是没有更好的解决方法了,结贴了。

#12


学习拿分

#1


你给字段city加上索引不就行了。

#2


同意楼上.

#3


这样的索引会指向很多记录的。这样的索引不会带来其他问题吗?

#4


所以会指向很多记录,但是你返回的少,就不会进行全表扫描了。

#5


但是建立索引之后还是会扫描大量的记录,有几万条。没见提高效率。例如一百万条记录中,只有三个不同的city,那平均下来建立索引都还是得扫描几十万条。
难道像这样的情形只能从其他方面考虑了吗?例如分表或者其他的?单纯从sql查询方面没有好办法了?

#6


我给你举个例子,补一下你的误区。

/*DDL Information For - test.song*/
-----------------------------------

Table   Create Table                                                                            
------  ----------------------------------------------------------------------------------------
song    CREATE TABLE `song` (                                                                   
          `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Autoincreament element',                
          `name` char(200) DEFAULT NULL,                                                        
          `datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,  
          `rank` int(11) NOT NULL,                                                              
          PRIMARY KEY (`id`),                                                                   
          KEY `k_name` (`name`)                                                                 
        ) ENGINE=MyISAM AUTO_INCREMENT=8102001 DEFAULT CHARSET=gbk        

select count(*) from song;
explain select count(1) from song where `name` = 't1';
count(*) 
8102000 
query result(1 records)
id select_type table type possible_keys key key_len ref rows Extra 
1 SIMPLE song ref k_name k_name 401 const 2 Using where; Using index 

我这个里面只是扫描了两行而已,虽然表有八百多行。

#7


#8


我按照6楼的建立了一个一样的表,弄了几条记录进去,例如name为aaa的记录有5条,其他记录有4条。
可是用explain还是显示要扫描4个记录啊,并不是就能够省下很多了。
mysql> explain select count(1) from song where name='aaa';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key    | key_len | ref   | rows | Extra                    |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
|  1 | SIMPLE      | song  | ref  | k_name        | k_name | 401     | const |    4 | Using where; Using index | 
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+

那么name为aaa的记录如果有10万条,还不是得扫描99999条记录?

难道跟mysql版本有关系?我的是5.0.27版本的。

#9


LZ,如果你的aaa记录非常多的话,这个就不能单纯从SQL语句方面优化了。

#10


select 1 from table1 where city= 'Beijing '

#11


看来单纯从SQL语句方面是没有更好的解决方法了,结贴了。

#12


学习拿分