标签: optimization

如何优化多个ORDER BY?

我在一个大约有 300,000 行且每列都有 B 树的表上遇到了缓慢的性能。

这适用于动态分页页面,其中查询是按需构建的,并且应用程序按照查询的指定顺序缓存主键。

对于此查询

explain analyze 
 SELECT supplier_management.buyer_purchase_order_id 
     FROM supplier_management 
     ORDER BY item_description DESC,
      item_number DESC,
      order_type ASC,
      possession_date DESC,
      shipment_type DESC,
      store_type DESC
Run Code Online (Sandbox Code Playgroud)

我得到这些结果:

排序(成本=51026.98..51750.35行=289348宽度=72)(实际时间=8229.280..12349.596行=289348循环=1)

排序键:商品描述、商品编号、订单类型、拥有日期、发货类型、商店类型

排序方式:外部合并磁盘:24744kB

-> 供应商管理上的顺序扫描(成本=0.00..10876.48行=289348宽度=72)(实际时间=0.015..187.426行=289348循环=1)

总运行时间:12407.064 毫秒

如何提高多列排序的性能?或者我应该用 C++ 来做?

表结构

buyer_purchase_order_id bigint
supplier_number bigint
supplier_name   character varying
purchase_order_number   bigint
store_number    integer
item_number bigint
item_description    character varying
project_type    character varying
order_date  integer
requested_arrival_date  integer
department  character varying
store_type  character varying
shipment_type   character varying
order_type  character varying
quantity_ordered    integer
quantity_allocation integer
quantity_staged integer …
Run Code Online (Sandbox Code Playgroud)

postgresql optimization order-by

5
推荐指数
1
解决办法
9092
查看次数

用于 concat select 的 MySQL 索引

对于以下查询

SELECT MAX(CONCAT(date, ' ', last_entry)) AS LAST_LOG
    FROM entry_log
    WHERE TRIM(LEADING 0 FROM card_no)='2948'
Run Code Online (Sandbox Code Playgroud)

我已经索引了

date
card_no
date,last_entry
date,last_entry,card_no
Run Code Online (Sandbox Code Playgroud)

我的解释显示

id  select_type     table       type    possible_keys   key             key_len     ref     rows    Extra   
1   SIMPLE          entry_log   index   NULL            date_last_card  158         NULL    103766  Using where; Using index
Run Code Online (Sandbox Code Playgroud)

我的解释扩展节目

id  select_type     table           type    possible_keys   key             key_len     ref     rows    filtered    Extra   
1     SIMPLE        entry_log       index   NULL            date_last_card  158         NULL    103766  100.00      Using where; Using index
Run Code Online (Sandbox Code Playgroud)

我想知道我可以删除/使用哪个索引,我的路径是否正确,我应该如何提高上述查询的执行时间?

CREATE TABLE `entry_log` (
 `id` int(11) NOT NULL AUTO_INCREMENT, …
Run Code Online (Sandbox Code Playgroud)

mysql index optimization index-tuning explain

5
推荐指数
1
解决办法
4223
查看次数

物化视图和索引

有没有办法强制 PostgreSQL 使用我在物化视图表上创建的索引?我尝试了移动列属性的所有可能组合,以使 Postgres 使用我的索引......

我有这张表:

=> explain select * from flight3mv1;
                         QUERY PLAN                          
-------------------------------------------------------------
 Seq Scan on flight3mv1  (cost=0.00..3.50 rows=150 width=26)
(1 row)
Run Code Online (Sandbox Code Playgroud)

当我在物化视图上创建索引时,我的查询计划没有任何变化。

=> create index flight3mv1index on flight3mv1(c_nation,s_nation);
=> analyze flight3mv1;
=> explain select * from flight3mv1 where c_nation='CHINA' and s_nation='CHINA';

                                      QUERY PLAN                                       
---------------------------------------------------------------------------------------
 Seq Scan on flight3mv1  (cost=0.00..4.25 rows=6 width=26)
   Filter: (((c_nation)::text = 'CHINA'::text) AND ((s_nation)::text = 'CHINA'::text))
(2 rows)
Run Code Online (Sandbox Code Playgroud)

这是我的 Flight3mv1 表:

=> \d flight3mv1
    Materialized view "public.flight3mv1"
  Column  |         Type          | Modifiers 
----------+-----------------------+-----------
 c_nation …
Run Code Online (Sandbox Code Playgroud)

postgresql performance optimization query-performance

5
推荐指数
1
解决办法
6926
查看次数

RDS上的Mysql避免index_merge

我对 mysql 优化和例程有一些经验,但最近有一些事情吸引了我。

我在 ec2 实例上使用本地 mysql 安装,然后刚刚迁移到 RDS,这样我就可以高枕无忧了。

问题是我的应用程序存在一些遗留问题,之前在 mysql 5.1 上运行,现在在 mysql 5.6 上运行。

我们的数据库是建立在index_merge将被mysql使用的前提下的,所以我们的索引不是复合的;它们都会影响单列;我知道这可能有多糟糕,也知道它有多糟糕,但到目前为止它运行良好;我现在无法真正更改它,因为我们有 300 多张桌子。

让我陷入麻烦的是我的一张桌子控制着库存。该表具有以下结构:

id (PK)
companyId (btree index)
productId (btree index)
transactionType (input, output or stock balance; btree index)
transactionDate (btree index)
transactionPrice
Run Code Online (Sandbox Code Playgroud)

以及其他一些并不重要的专栏。

当我运行选择查询来获取给定产品的最后价格时,如下所示:

SELECT 
    transactionPrice
FROM
    stock
WHERE
    productId = x
        AND transactionType = 'input'
        AND companyId = y
        AND transactionDate < '2017-07-07'
ORDER BY transactionDate DESC
LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

我所期望的是 MySQL 会合并(很可能)非常具体的 ProductId 和 companyId 索引,并读取大约 4 行;但实际发生的情况是,MySQL 决定通过对 transactionDate 进行排序而不将其合并到任何其他索引来迭代超过 …

mysql index optimization

5
推荐指数
1
解决办法
1485
查看次数

如何识别导致事务日志增长的事务?

我有一个 20 GB 的数据库,它的事务日志坚持超过 7 GB。

当我使用此脚本找出该数据库中最大对象的大小时,我发现它们相对较小。

在此输入图像描述

我一直在使用默认跟踪来查看此事务日志何时自动增长,但我没有发现。

DECLARE @path NVARCHAR(260);

SELECT 
   @path = REVERSE(SUBSTRING(REVERSE([path]), 
   CHARINDEX(CHAR(92), REVERSE([path])), 260)) + N'log.trc'
FROM    sys.traces
WHERE   is_default = 1;

SELECT 
   DatabaseName,
   [FileName],
   SPID,
   Duration,
   StartTime,
   EndTime
FROM sys.fn_trace_gettable(@path, DEFAULT)
WHERE EventClass = 93 -- log autogrow event
ORDER BY StartTime DESC;
Run Code Online (Sandbox Code Playgroud)

我还尝试了这里的一些脚本,以检查哪些事务正在填充日志,但找不到任何事务。

我相信一定有一些非常长的事务同时进行,或者至少有一个较长的事务正在执行。

我怎样才能检查这些(long transactions in the database)?

在 LIVE 中,这是一个完整恢复模式数据库,是alwayson 的一部分。在 TEST 中,这是一个简单的恢复模式数据库,但由于所有作业都在那里,日志仍然增长到 7GB。

sql-server optimization transaction transaction-log sql-server-2016

5
推荐指数
1
解决办法
2515
查看次数

优化大记录删除流程

我正在创建一个反映我们生产数据库的数据库,但更轻且匿名 - 用于本地开发目的。

为了确保我们有足够的数据可供工程团队使用,我将删除所有日期设置updated_at为一年多前的客户。简单的过程是保留新用户,但保留旧用户或不活跃用户。

为此,我创建了一个存储过程。

DELIMITER //
CREATE PROCEDURE delete_old_customers()
BEGIN
    SET @increment = 0;
    customer_loop: LOOP

        DELETE FROM customers 
        WHERE id BETWEEN @increment AND @increment+999
        AND updated_at < DATE_SUB(CURRENT_DATE(), INTERVAL 1 YEAR);

        IF @increment > (SELECT MAX(id) FROM customers) THEN
            LEAVE customer_loop;
        END IF;

        SET @increment = @increment + 1000;

    END LOOP customer_loop;
END //
DELIMITER ;

CALL delete_old_customers();

DROP PROCEDURE delete_old_customers;
Run Code Online (Sandbox Code Playgroud)

因此,此过程将删除分批分成 1000 个组,并一直运行,直到没有更多客户需要处理。

我运行这样的程序:

mysql "$MYSQLOPTS" devdb < ./queries/customer.sql
Run Code Online (Sandbox Code Playgroud)

其中$MYSQLOPTS指的是具有以下选项的 my.cnf 文件:

[mysqld] …
Run Code Online (Sandbox Code Playgroud)

mysql performance stored-procedures optimization query-performance

5
推荐指数
1
解决办法
4358
查看次数

了解查询计划更改的原因

我们的 ERP 系统存在一些性能问题。06:00 左右,问题开始出现。长话短说; 我的一位同事执行了DBCC FREEPROCCACHE(我知道这不是首选操作,但这不是重点)。之后,他重新启动了整个 ERP 应用程序,而不是数据库引擎。这似乎没有帮助。我查看了查询存储,发现查询计划在 06:05 左右发生了更改。我尝试强制执行旧计划,性能问题就消失了。

我比较了 2 个计划 XML,发现两者都基于相同的统计数据(更新日期完全相同)。索引上的更改数量不同,但这不会触发更新统计信息,因为否则新的查询计划将为所使用的统计信息提供新的日期。我检查了涉及的表的所有统计信息,但自上次维护工作以来,它们没有更新。最后一次维护作业在本周末运行,这也是两个查询计划中使用的统计信息的更新日期。

该查询是参数化查询,所以我有点不清楚为什么查询计划突然改变。我认为恰恰相反,查询突然运行缓慢,因为相同的计划用于不同的参数。这里的情况似乎并非如此,因为我强制使用旧的查询计划。

该查询来自一些检索订单的定制工作。现在,我怀疑有人发出了参数化查询,该查询会返回一个非常大的数据集,从而减慢 ERP 系统的速度。然后,我的同事运行了一个DBCC FREEPROCCACHE命令,根据本周末的新统计数据触发了查询计划的重新编译。当前查询继续运行,他决定重新启动 ERP 应用程序。现在,使用新的查询计划,所有新查询都会变慢,直到我强制使用旧的查询计划。

这能是解释吗?我有点怀疑,因为当统计数据发生变化时,SQL Server会触发重新编译,所以计划应该在索引维护作业之后已经重新编译。

我想我在这里遗漏了一些东西,但我不确定是什么。它是SQL Server 2016 Standard,是ERP系统的专用服务器。

编辑 15-4-2020 12:17:既然我写了这个...我认为问题在于DBCC FREEPROCCACHE第一次执行有问题的参数化查询的参数使用了不同的参数,这导致 SQL Server 重新编译(坏)计划。或者我还缺少什么吗?

sql-server optimization execution-plan

5
推荐指数
1
解决办法
1559
查看次数

如何优化2.5亿行的Mysql数据库批量插入和选择

我是一名学生,他的任务是设计传感器数据数据库。我的大学目前有一个大型数据库,里面充满了这些数据,但存储的很多内容都是不必要的。他们希望我从现有数据库中提取一些字段,并将其插入到一个新数据库中,该新数据库只包含“必需品”。我需要从旧行中提取每一行,并每天获取一次新数据。

  • 有1500个传感器。
  • 他们每分钟生成一个读数。
  • 每天约210万次阅读
  • 当前数据库约有 2.5 亿行。

将执行的查询通常是在给定时间跨度之间选择一组传感器的传感器读数。

我最初对于大量数据带来的复杂性还很天真,所以我严重低估了这项任务所需的时间。因此,加上我无法从家里访问服务器,我在这里寻求帮助和意见。

最初的设计如下所示:

CREATE TABLE IF NOT EXISTS SENSORS (
    ID smallint UNSIGNED NOT NULL AUTO_INCREMENT,
    NAME varchar(500) NOT NULL UNIQUE,
    VALUEFACETS varchar(500) NOT NULL,
    PRIMARY KEY (ID)
); 

CREATE TABLE IF NOT EXISTS READINGS (
    ID int UNSIGNED AUTO_INCREMENT,
    TIMESTAMP int UNSIGNED INDEX NOT NULL,
    VALUE float NOT NULL,
    STATUS int NOT NULL,
    SENSOR_ID smallint UNSIGNED NOT NULL,
    PRIMARY KEY (ID),
    FOREIGN KEY (SENSOR_ID) REFERENCES SENSORS(ID)
);
Run Code Online (Sandbox Code Playgroud)

设计问题

我的第一个问题是我是否应该为读数保留自动递增密钥,或者在 TIMESTAMP(UNIX 纪元)和 SENSOR_ID …

mysql innodb database-design optimization

5
推荐指数
1
解决办法
5750
查看次数

优化匹配数组前 N 项的查询

我现在正在使用充满国际象棋游戏数据的 Postgres 数据库,其中每个游戏都是“记录”表中的一行。玩家的动作和这些动作的(可选)计算机评估都有自己的列并存储为数组。

我编写了一个查询来检索指定的开局动作序列的所有评估。(你可能认为计算机的评估会是一致的 - 但事实并非如此。)开局序列的长度是任意的 - 可以是一步,也可以是三十步。

下面是一个示例查询,它查找以相同的十步开局序列开始的所有游戏,然后对于每个带有评估的游戏,返回计算机对游戏中该点的评估 -

SELECT evaluation[10]
FROM records
WHERE moves[1:10]::text[] = ARRAY['b4', 'e5', 'Bb2', 'd6', 'Nf3', 'Nf6', 'g3', 'Bg4', 'Bg2', 'h5']::text[]
AND evaluation IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)

我不确定它是否相关,但移动数据始终是 2-6 个字符的字母数字字符串,并且计算机评估大部分是小数(正数和负数),但确实包括偶尔的特殊字符(强制将死者有一个 octothorpe前缀)。

这是表描述的相关片段 -

     Column      |              Type              | 
-----------------+--------------------------------+-
 id              | bigint                         | 
 moves           | character varying(255)[]       |  
 evaluation      | character varying(255)[]       | 
    "records_pkey" PRIMARY KEY, btree (id)
Access method: heap
Run Code Online (Sandbox Code Playgroud)

这是来自 EXPLAIN ANALYZE 的查询计划:

 Gather  (cost=1000.00..736354.70 rows=905 width=516) (actual time=28251.267..28253.139 rows=0 loops=1)
   Workers Planned: 2 …
Run Code Online (Sandbox Code Playgroud)

postgresql index optimization array postgresql-performance

5
推荐指数
1
解决办法
1086
查看次数

Select * Order by 与 Select column 按性能排序

我有以下表格

Create Table dbo.product
(
productId varchar(100) primary key,
productStatus varchar(100),
productRegion varchar(100),
productCreated  datetime,
productUpdated datetime
)
Go

declare @id int = 1
while @id <= 100
Begin

Insert Into dbo.product values ('product'+cast(@id as varchar(10)),'Active','North',getdate(),getdate())
    set @id = @id + 1
End

set @id = 1
while @id <= 100
Begin

Insert Into dbo.product values ('inprod'+ cast(@id as varchar(10)),'InActive','South',getdate(),getdate())
    set @id = @id + 1
End
Go

Create Table dbo.productRef
(
productRef int Identity(1,1) primary key,
productId varchar(100),
productName …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization query-performance

5
推荐指数
2
解决办法
3655
查看次数