在千万级的数据库查询中,怎样提高服从?
1)数据库设计方面
a. 对查询进行优化,应只管避免全表扫描,起首应思量在 where 及 order by 涉及的列上创建索引。
b. 应只管避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃利用索引而进行全表扫
描如:select id from t where num is null 可以在 num 上设置默认值 0,确保表中 num 列没有 null 值,然后这样查询 :
select id from t where num=0
c. 并不是所有索引对查询都有用,SQL 是根据表中数据来进行查询优化的,当索引列有大量数据重复时,查询大概
不会去利用索引,如一表中有字段 sex,male、female 几乎各一半,那么即使在 sex 上建了索引也对查询服从起不
了作用。
d. 索引并不是越多越好,索引固然可以提高相应的 select 的服从,但同时也低落了 insert 及 update 的
效 率 , 因 为 insert 或 update 时有大概会重修索引,所以怎样建索引需要慎重思量,视具体环境而定。一
个表的索引数最好不要高出 6 个,若太多则应思量一些不常利用到的列上建的索引是否有必要。
e. 应尽大概的避免更新索引数据列,因为索引数据列的顺序就是表记载的物理存储顺序,一旦该列值改变将导致
整个表记载的顺序的调整,会耗费相当大的资源。若应用系统需要频繁更新索引数据列,那么需要思量是否应将该索
引建为索引。
f. 只管利用数字型字段,若只含数值信息的字段只管不要设计为字符型,这会低落查询和连接的性能,并会增
加存储开销。这是因为引擎在处置处罚查询和连接时会逐个比较字符串中每一个字符,而对于数字型而言只需要比较一
次就够了。
g. 尽大概的利用 varchar/nvarchar 代替 char/nchar ,因为起首变长字段存储空间小,可以节省存储空间, 其次
对于查询来说,在一个相对较小的字段内搜索服从显然要高些。
h. 只管利用表变量来代替临时表。假如表变量包含大量数据,请留意索引非常有限(只有主键索引)。
i.
避免频繁创建和删除临时表,以减少系统表资源的消耗。
j. 临时表并不是不可利用,得当地利用它们可以使某些例程更有用,例如,当需要重复引用大型表或常用表中
的某个数据集时。但是,对于一次性事件,最好利用导出表。
k. 在新建临时表时,假如一次性插入数据量很大,那么可以利用 select into 代 替 create table,避免造成大量 log ,以提高速率;假如数据量不大,为了和缓系统表的资源,应先 create table,然后 insert。
l. 假如利用到了临时表,在存储过程的末了务必将所有的临时表显式删除,先 truncate table , 然 后 drop
table ,这样可以避免系统表的较长时间锁定。
2)
SQL 语句方面
a. 应只管避免在 where 子句中利用!=或操纵符,否则将引擎放弃利用索引而进行全表扫描。
b. 应只管避免在 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
c. in 和 not in 也要慎用,否则会导致全表扫描,如: select id from t where num in(1,2,3) 对于连续的数
值,能用 between 就不要用 in 了 : select id from t where num between 1 and 3
d. 下面的查询也将导致全表扫描: select id from t where name like ‘%abc%’
e. 假如在 where 子句中利用参数,也会导致全表扫描。因为 SQL 只有在运行时才会剖析局部变量,但优化程
序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然而,假如在编译时创建访问计划,变量的值还是未
知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描: select id from t where num=@num
可以改为强制查询利用索引: select id from t with(index(索引名)) where num=@num
f. 应只管避免在 where 子句中对字段进行表达式操纵,这将导致引擎放弃利用索引而进行全表扫描。如:
select id from t where num/2=100 应改为: select id from t where num=100*2
g. 应只管避免在 where 子句中对字段进行函数操纵,这将导致引擎放弃利用索引而进行全表扫描。如:select id from t
where substring(name,1,3)= ‘ abc ’ – name
以
abc
开 头 的
id select id from t where
datediff(day,createdate,’2005-11-30′)=0–‘2005-11-30’生成的 id 应改为: select id from t where name like ‘abc%’
<span style="color: #121212; --tt-darkmode-color: #A3A3A3;">select id from t where createdate>=’2005-11-30′ and createdate |