标签: optimization

如何优化 MySQL 中的 InnoDB 表

我一直在研究如何仅优化 MySQL 中的碎片表,并查看了有关优化表的这篇文章。它基本上对包含任何表的 information_schema 数据库执行查询,data_free > 0OPTIMIZE仅针对这些表构建 SQL 语句。我运行了这个查询,它确定了 148 个用于优化的表。所有标识的表都是 InnoDB 表。执行结果优化 SQL 脚本后,我重新运行原始脚本以识别碎片表,并在第一遍返回完全相同的表。

我看到过关于 InnoDB 表和OPTIMIZE命令的相互冲突的帖子。有人说这OPTIMIZE不适用于 InnoDB 表,您需要运行ALTER TABLE table_name ENGINE=INNODB. 其他人说在对 InnoDB 表执行时OPTIMIZE实际上调用了ALTER TABLE命令。考虑到这一点,我ALTER TABLE对标识为碎片化的 InnoDB 表之一运行了该命令 ( data_free > 0),并发现该表data_free之后没有更改。它仍然大于0。我也重新启动了MySQL并检查了它只是发现相同的结果。

现在,我们的组织中有几台运行 MySQL 5.5.29 的服务器,我对所有服务器进行了查询以识别任何 InnoDB 表,DATA_FREE=0 or NULL但没有返回。它们都大于零。

我还OPTIMIZE针对几个大于零的MyISAM表运行了该命令,DATA_FREE然后验证它是否为零。

任何人都可以为我解释一下吗?从 InnoDB 表中删除碎片的正确方法是什么?确定碎片化 InnoDB 表的正确方法是什么?

谢谢

mysql innodb optimization

10
推荐指数
1
解决办法
2万
查看次数

有没有什么命令可以自动一一优化所有MySQL表?

我执行以下命令行语句来优化表: optimize table tablename;

是否有任何命令或语句可以将所选数据库中的所有表一一优化?

mysql optimization mysql-5.1

10
推荐指数
2
解决办法
3万
查看次数

我如何“暗示”递归 CTE 的基数?

我使用以下递归 CTE 作为最小示例,但总的来说,优化器必须对递归 CTE 使用默认的“猜测”基数:

with recursive w(n) as ( select 1 union all select n+1 from w where n<5 ) select * from w;
/*
 n
---
 1
 2
 3
 4
 5
*/

explain analyze
with recursive w(n) as ( select 1 union all select n+1 from w where n<5 ) select * from w;
/*
                                                    QUERY PLAN
-------------------------------------------------------------------------------------------------------------------
 CTE Scan on w  (cost=2.95..3.57 rows=31 width=4) (actual time=0.005..0.020 rows=5 loops=1)
   CTE w
     ->  Recursive Union  (cost=0.00..2.95 rows=31 width=4) (actual …
Run Code Online (Sandbox Code Playgroud)

postgresql optimization cte postgresql-9.3

10
推荐指数
1
解决办法
722
查看次数

多行插入与多个单行插入

在我的应用程序中,我尽可能地进行多行插入,因为它减少了数据库和应用程序之间的往返次数。

不过,我很好奇,还有其他好处吗?例如,如果像这样一次插入多行:

insert into tbl (c1, c2) values
(v1, v2)
(v3, v4)
Run Code Online (Sandbox Code Playgroud)

相对:

insert into tbl (c1, c2) values (v1, v2)
insert into tbl (c1, c2) values (v3, v4)
Run Code Online (Sandbox Code Playgroud)

并且表有索引,索引是在第一种情况下计算一次,在第二种情况下计算两次吗?还是每次插入总是一次?假设两个查询在同一个事务中。

我正在使用 PostgreSQL。

postgresql index optimization

10
推荐指数
1
解决办法
1万
查看次数

尽管我希望寻求帮助,但仍在进行扫描

我需要优化一个SELECT语句,但 SQL Server 总是执行索引扫描而不是查找。这是查询,当然,在存储过程中:

CREATE PROCEDURE dbo.something
  @Status INT = NULL,
  @IsUserGotAnActiveDirectoryUser BIT = NULL    
AS

    SELECT [IdNumber], [Code], [Status], [Sex], 
           [FirstName], [LastName], [Profession], 
           [BirthDate], [HireDate], [ActiveDirectoryUser]
    FROM Employee
    WHERE (@Status IS NULL OR [Status] = @Status)
    AND 
    (
      @IsUserGotAnActiveDirectoryUser IS NULL 
      OR 
      (
        @IsUserGotAnActiveDirectoryUser IS NOT NULL AND       
        (
          @IsUserGotAnActiveDirectoryUser = 1 AND ActiveDirectoryUser <> ''
        )
        OR
        (
          @IsUserGotAnActiveDirectoryUser = 0 AND ActiveDirectoryUser = ''
        )
      )
    )
Run Code Online (Sandbox Code Playgroud)

这是索引:

CREATE INDEX not_relevent ON dbo.Employee
(
    [Status] …
Run Code Online (Sandbox Code Playgroud)

index sql-server optimization sql-server-2012

9
推荐指数
1
解决办法
1228
查看次数

如何针对索引改进受 DateAdd() 约束的视图中 1 行的估计

使用 Microsoft SQL Server 2012 (SP3) (KB3072779) - 11.0.6020.0 (X64)。

给定一个表和索引:

create table [User].[Session] 
(
  SessionId int identity(1, 1) not null primary key
  CreatedUtc datetime2(7) not null default sysutcdatetime())
)

create nonclustered index [IX_User_Session_CreatedUtc]
on [User].[Session]([CreatedUtc]) include (SessionId)
Run Code Online (Sandbox Code Playgroud)

以下每个查询的实际行数为 310 万,估计行数显示为注释。

当这些查询在 View 中提供另一个查询,由于 1 行估计,优化器选择循环连接。 如何在此基础级别改进估计以避免覆盖父查询连接提示或求助于 SP?

使用硬编码日期效果很好:

 select distinct SessionId from [User].Session -- 2.9M (great)
  where CreatedUtc > '04/08/2015'  -- but hardcoded
Run Code Online (Sandbox Code Playgroud)

这些等效查询与视图兼容,但都估计为 1 行:

select distinct SessionId from [User].Session -- 1
 where CreatedUtc …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization view sql-server-2012

9
推荐指数
2
解决办法
372
查看次数

优化大表上的 LATERAL JOIN 查询

我正在使用 Postgres 9.5。我有一个记录来自多个网站的页面点击量的表格。该表包含从 2016 年 1 月 1 日到 2016 年 6 月 30 日的大约 3200 万行。

CREATE TABLE event_pg (
   timestamp_        timestamp without time zone NOT NULL,
   person_id         character(24),
   location_host     varchar(256),
   location_path     varchar(256),
   location_query    varchar(256),
   location_fragment varchar(256)
);
Run Code Online (Sandbox Code Playgroud)

我正在尝试调整一个查询,该查询计算执行给定页面命中序列的人数。该查询旨在回答诸如“有多少人查看了主页,然后访问了帮助站点,然后查看了感谢页面”之类的问题?结果看起来像这样

?????????????????????????????????????????
?  home-page ? help site  ? thankyou    ?
?????????????????????????????????????????
? 10000      ? 9800       ?1500         ?
?????????????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

请注意数字正在减少,这是有道理的,因为查看主页的 10000 人 9800 继续访问了帮助站点,而其中 1500 人继续点击了感谢页面。

3 步序列的 SQL 使用横向连接,如下所示:

SELECT 
  sum(view_homepage) AS view_homepage,
  sum(use_help) AS use_help,
  sum(thank_you) AS thank_you
FROM ( …
Run Code Online (Sandbox Code Playgroud)

postgresql performance optimization greatest-n-per-group postgresql-performance

9
推荐指数
1
解决办法
8114
查看次数

为什么这个执行计划有计算标量?

我有一个简单的SELECT声明。

USE [AdventureWorks2014]
GO

SELECT *
FROM Sales.SalesOrderDetail sod
Run Code Online (Sandbox Code Playgroud)

执行计划有两个Compute Scalar.

显示计算标量的执行计划 为什么是这样?我原以为只得到Index Scan或者Table Scan?

第一个(最右边的)有

 [[AdventureWorks2014].[Sales].[SalesOrderDetail].LineTotal] = Scalar Operator(isnull(CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2014].[Sales].[SalesOrderDetail].[UnitPrice] as [sod].[UnitPrice],0)*((1.0)-CONVERT_IMPLICIT(numeric(19,4),[AdventureWorks2014].[Sales].[SalesOrderDetail].[UnitPriceDiscount] as [sod].[UnitPriceDiscount],0))*CONVERT_IMPLICIT(numeric(5,0),[AdventureWorks2014].[Sales].[SalesOrderDetail].[OrderQty] as [sod].[OrderQty],0),(0.000000)))
Run Code Online (Sandbox Code Playgroud)

当第二个有:

[[sod].LineTotal] = Scalar Operator([AdventureWorks2014].[Sales].[SalesOrderDetail].[LineTotal] as [sod].[LineTotal])
Run Code Online (Sandbox Code Playgroud)

performance sql-server optimization execution-plan

9
推荐指数
1
解决办法
3399
查看次数

主键上的自连接

考虑这个由N自连接组成的查询:

select
    t1.*
from [Table] as t1
join [Table] as t2 on
    t1.Id = t2.Id
-- ...
join [Table] as tN on
    t1.Id = tN.Id
Run Code Online (Sandbox Code Playgroud)

它生成一个执行计划,其中包含 N 次聚集索引扫描和 N-1 次合并连接。

老实说,我看不出有任何理由不优化所有连接并仅执行一次聚集索引扫描,即将原始查询优化为:

select
    t1.*
from [Table] as t1
Run Code Online (Sandbox Code Playgroud)

问题

  • 为什么连接没有被优化掉?
  • 说每个连接都不会改变结果集在数学上是不正确的吗?

测试:

  • 源服务器版本:SQL Server 2014 (12.0.4213)
  • 源数据库引擎版:Microsoft SQL Server 标准版
  • 源数据库引擎类型:独立 SQL Server
  • 兼容级别:SQL Server 2008 (100)

查询没有意义;它刚刚出现在我的脑海中,我现在对它很好奇。

这是表创建和 3 个查询的小提琴:使用inner join's、使用left join's 和混合。您也可以在那里查看执行计划。

似乎left join在结果执行计划中消除了inner joins而s 则没有。不过还是不明白为什么 …

sql-server optimization sql-server-2014

9
推荐指数
1
解决办法
1734
查看次数

为什么这个带有参数的递归 CTE 在使用文字时不使用索引?

我在树结构上使用递归 CTE 来列出树中特定节点的所有后代。如果我在我的WHERE子句中写了一个文字节点值,SQL Server 似乎实际上只是将 CTE 应用于该值,给出一个实际行数较低的查询计划,等等

带有文字值的查询计划

但是,如果我将该值作为参数传递,它似乎实现了(假脱机)CTE,然后在事后对其进行过滤

带参数值的查询计划

我可能读错了计划。我没有注意到性能问题,但我担心 CTE 的实现可能会导致较大数据集出现问题,尤其是在繁忙的系统中。此外,我通常将这种遍历本身复合:我遍历祖先并返回后代(以确保收集所有相关节点)。由于我的数据如何,每组“相关”节点都相当小,因此实现 CTE 没有意义。当 SQL Server 似乎意识到 CTE 时,它在“实际”计数中给了我一些相当大的数字。

有没有办法让查询的参数化版本表现得像文字版本?我想把 CTE 放在一个可重用的视图中。

用文字查询:

CREATE PROCEDURE #c AS BEGIN;
    WITH descendants AS (SELECT
         t.ParentId Id
        ,t.Id DescendantId
    FROM #tree t
    WHERE t.ParentId IS NOT NULL
    UNION ALL SELECT
         d.Id
        ,t.Id DescendantId
    FROM descendants d
    JOIN #tree t ON d.DescendantId = t.ParentId)
    SELECT d.*
    FROM descendants d
    WHERE d.Id = 24
    ORDER BY d.Id, d.DescendantId; …
Run Code Online (Sandbox Code Playgroud)

sql-server optimization cte execution-plan recursive

9
推荐指数
2
解决办法
1306
查看次数