SQL中日志记录表的适当查询和索引
假设有一个名为“log”的表,其中有大量记录 应用程序通常通过简单的SQL检索数据:SQL中日志记录表的适当查询和索引,sql,mysql,sql-server,oracle,database-agnostic,Sql,Mysql,Sql Server,Oracle,Database Agnostic,假设有一个名为“log”的表,其中有大量记录 应用程序通常通过简单的SQL检索数据: SELECT * FROM log WHERE logLevel=2 AND (creationData BETWEEN ? AND ?) logLevel和creationData都有索引,但是记录的数量使得检索数据的时间更长 我们如何解决这个问题?有几件事 您是否需要所有列,人们通常会选择*,因为他们太懒了,无法列出表中15列中的5列 获得更多的RAM,您拥有的RAM越多,缓存中可以存储的数据就越多,
SELECT *
FROM log
WHERE logLevel=2 AND (creationData BETWEEN ? AND ?)
logLevel
和creationData
都有索引,但是记录的数量使得检索数据的时间更长
我们如何解决这个问题?有几件事
您是否需要所有列,人们通常会选择*,因为他们太懒了,无法列出表中15列中的5列
获得更多的RAM,您拥有的RAM越多,缓存中可以存储的数据就越多,这比从磁盘读取数据快1000倍
您是否需要所有列,人们通常会选择*,因为他们太懒了,无法列出表中15列中的5列
获取更多的RAM,您拥有的RAM越多,缓存中可以存储的数据就越多,这比从磁盘读取数据快1000倍1:永远不要使用
Select*
2:确保索引正确,统计数据是最新的
3:(可选)如果您发现在某个特定时间后没有查看日志数据(根据我的经验,如果发生在一周前,我可能不需要日志),请设置一个作业,将其归档到某个备份,然后删除未使用的记录。这将减小表格大小,减少搜索表格所需的时间。1:切勿使用
Select*
2:确保索引正确,统计数据是最新的
3:(可选)如果您发现在某个特定时间后没有查看日志数据(根据我的经验,如果发生在一周前,我可能不需要日志),请设置一个作业,将其归档到某个备份,然后删除未使用的记录。这将减小表的大小,减少搜索表所需的时间。查看执行计划/“解释计划”结果-如果您正在检索大量数据,那么您几乎无法改进性能-您可以尝试将
SELECT
语句更改为只包含您感兴趣的列,但是,它不会改变您正在执行的逻辑读取的数量,因此我怀疑它只会对性能产生可忽略的影响
如果您只检索少量记录,那么LogLevel索引和CreationDate上的索引应该可以做到这一点
更新:SQL server主要用于查询大型数据库的小子集(例如,从数百万数据库中返回单个客户记录)。它并没有真正准备好返回真正大的数据集。如果您返回的数据量确实很大,那么您只能做一定量的数据,因此我不得不问:
你真正想要实现的是什么
- 如果您向用户显示日志消息,那么他们一次只对一小部分感兴趣,因此您可能还想研究分页SQL数据的有效方法—如果您一次只返回500条左右的记录,那么速度应该非常快
- 如果您试图进行某种统计分析,那么您可能希望将数据复制到更适合统计分析的数据存储中。(不确定是什么,但这不是我的专业领域)
SELECT
语句,使其仅包含您感兴趣的列,但是,它不会改变您正在执行的逻辑读取的数量,因此我怀疑它只会对性能产生可忽略的影响
如果您只检索少量记录,那么LogLevel索引和CreationDate上的索引应该可以做到这一点
更新:SQL server主要用于查询大型数据库的小子集(例如,从数百万数据库中返回单个客户记录)。它并没有真正准备好返回真正大的数据集。如果您返回的数据量确实很大,那么您只能做一定量的数据,因此我不得不问:
你真正想要实现的是什么
- 如果您向用户显示日志消息,那么他们一次只对一小部分感兴趣,因此您可能还想研究分页SQL数据的有效方法—如果您一次只返回500条左右的记录,那么速度应该非常快
- 如果您试图进行某种统计分析,那么您可能希望将数据复制到更适合统计分析的数据存储中。(不确定是什么,但这不是我的专业领域)
是否需要一次将所有返回的数据保存在内存中?在检索端,每行分配多少内存?你一次需要多少内存?你能重复使用一些内存吗 是否需要所有列?第一步应该是只选择您实际需要检索的内容 另一个方面是数据到达应用程序后如何处理(填充数据集/按顺序读取/?) 在处理应用程序方面可能有一些改进的潜力 你应该回答这些问题
CREATE INDEX i_log_1 ON log (creationData, logLevel);
DECLARE
l_ownname VARCHAR2(255) := 'owner'; -- Owner (schema) of table to analyze
l_tabname VARCHAR2(255) := 'log'; -- Table to analyze
l_estimate_percent NUMBER(3) := 5; -- Percentage of rows to estimate (NULL means compute)
BEGIN
dbms_stats.gather_table_stats (
ownname => l_ownname ,
tabname => l_tabname,
estimate_percent => l_estimate_percent,
method_opt => 'FOR ALL INDEXED COLUMNS',
cascade => TRUE
);
END;
ANALYZE TABLE log COMPUTE STATISTICS FOR ALL INDEXED COLUMNS;