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越多,缓存中可以存储的数据就越多,

假设有一个名为“log”的表,其中有大量记录

应用程序通常通过简单的SQL检索数据:

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;