-
字段长度的设置要合理
数据库中的表越小,在它上面执行的查询也就会越快。
省份”或者“性别”,我们可以将它们定义为ENUM类型。
数值型数据被处理起来的速度要比文本类型快得多。
把字段设置为NOT NULL,这样在将来执行查询的时候,数据库不用去比较NULL
-
使用连接(JOIN)来代替子查询(IN)
select *
from car a
left join userinfo b on a.uid=b.uidselect * from userinfo
where uid in (
select uid from car
) #有车的人 临时表 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
-
应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,
如:
select id from t where num is null
可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:
select id from t where num=0
应尽量避免在where子句中使用 != 操作符,否则将引擎放弃使用索引而进行全表扫描。
> select * from table where age != 3
>
>
> select * from table where age>3
> union all
> select * from table where age<3
-
应尽量避免在where子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,
如:
select id from t where num=10 or num=20
可以这样查询:
select id from t where num=10
union all
select id from t where num=20 -
应尽量避免使用in 和 not in ,否则会导致全表扫描,
如:
用exists代替
// 不走索引,效率低,适用于外表大而内表小
select id from t where num in(1,2,3)
对于连续的数值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
// 走索引,效率高,通常适用于外表小而内表大
select id from t where exists(select id from t where XXX)
模糊查询也将导致全表扫描:
> select id from t where name like 'abc%'
-
应尽量避免在where子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。
如:
select id from t where num/2=100
应改为:
select id from t where num=100*2
-
应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。
如:
右模糊和左模糊
select id from t where substring(name,1,3)='abc'
应改为:
select id from t where name like 'abc%'
在使用索引字段作为条件时,如果该索引是复合索引,
那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引, 否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致。
> create index myindex on userinfo(uname,upass,sex);
>
>
> ```
> oracle的查询是 where
> 默认是从右向左执行
> select * from table where wg=true and sex=f
> 但是:11G之前,你必须写成这样。
> 11G:已经提供了优化。
> mysql:
> 从左到右
> select * from table where sex=f and wg=true
>
> 有索引的项目:
> 应该放前面还是后面
> ```
- 很多时候用 exists 代替 in 是一个好的选择:
> select num from a where num in(select num from b)
>
>
> 用下面的语句替换:
>
>
> select num from a where exists(select 1 from b where num=a.num)
>
> ```sql
> #3.554s
> explain SELECT *
> FROM product_seller_goods goods
> WHERE goods.product_sys_code in ( SELECT bar.product_sys_code FROM product_seller_goods_barcode bar );
>
> #2.178s
> explain SELECT *
> FROM product_seller_goods goods
> WHERE NOT EXISTS ( SELECT 1 FROM product_seller_goods_barcode WHERE goods.product_sys_code = product_sys_code )
> ```
- 并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,
当索引列有大量数据重复时,SQL查询可能不会去利用索引,
> 如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。
-
尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型,
这会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会逐个比较字符串中每个字符,而数字型只需要比较一次就够了。
任何地方都不要使用 select * from t ,用具体的字段列表代替“ * ”,不要返回用不到的任何字段
尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。
二者都能使用尽量使用where(与having比较)
where 先过滤(数据就少了)再分组-
确保任何的GROUP BY和ORDER BY中的表达式只涉及到一个表中的列,这样MySQL才有可能使用索引来优化。
设计:
用户表
uid uname 等100多个字段10张表
车表:
cid cname uid<FK> uname t1key t2key t3key t4key t5key (50个)
表分区 分表
-
查询所有车
1:调优MySQL服务器时,配置的两个变量
key_buffer_size和 table_open_cache2:用多个小表代替一个大表,注意不要过度设计
3:批量插入代替循环单条插入
4:合理控制缓存空间大小,一般来说其大小设置为几十兆比较合适
5:可以通过SQL_CACHE和SQL_NO_CACHE来控制某个查询语句是否需要进行缓存
最后的忠告是不要轻易打开查询缓存,特别是写密集型应用。如果你实在是忍不住,可以将query_cache_type设置为DEMAND,这时只有加入SQL_CACHE的查询才会走缓存,其他查询则不会,这样可以非常自由地控制哪些查询需要被缓存。6:选择数据类型只要遵循小而简单的原则就好,越小的数据类型通常会更快,占用更少的磁盘、内存,处理时需要的CPU周期也更少。越简单的数据类型在计算时需要更少的CPU周期,
比如,整型就比字符操作代价低,因而会使用整型来存储ip地址,使用DATETIME来存储时间,而不是使用字符串。7:通常来说把可为NULL的列改为NOT NULL不会对性能提升有多少帮助,只是如果计划在列上创建索引,就应该将该列设置为NOT NULL。
8:对整数类型指定宽度,比如INT(11),没有任何卵用。INT使用32位(4个字节)存储空间,那么它的表示范围已经确定,所以INT(1)和INT(20)对于存储和计算是相同的。
9:通常来讲,没有太大的必要使用DECIMAL数据类型。即使是在需要存储财务数据时,仍然可以使用BIGINT。比如需要精确到万分之一,那么可以将数据乘以一百万然后使用BIGINT存储。这样可以避免浮点数计算不准确和DECIMAL精确计算代价高的问题。
10:大多数情况下没有使用枚举类型的必要,其中一个缺点是枚举的字符串列表是固定的,添加和删除字符串(枚举选项),必须使用ALTER TABLE(如果只是在列表末尾追加元素,不需要重建表)。
11:创建高性能索引