我一直在研究如何仅优化 MySQL 中的碎片表,并查看了有关优化表的这篇文章。它基本上对包含任何表的 information_schema 数据库执行查询,data_free > 0并OPTIMIZE仅针对这些表构建 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 表的正确方法是什么?
谢谢
我执行以下命令行语句来优化表:
optimize table tablename;
是否有任何命令或语句可以将所选数据库中的所有表一一优化?
我使用以下递归 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) 在我的应用程序中,我尽可能地进行多行插入,因为它减少了数据库和应用程序之间的往返次数。
不过,我很好奇,还有其他好处吗?例如,如果像这样一次插入多行:
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。
我需要优化一个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) 使用 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) 我正在使用 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
我有一个简单的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) 考虑这个由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)
测试:
查询没有意义;它刚刚出现在我的脑海中,我现在对它很好奇。
这是表创建和 3 个查询的小提琴:使用inner join's、使用left join's 和混合。您也可以在那里查看执行计划。
似乎left join在结果执行计划中消除了inner joins而s 则没有。不过还是不明白为什么 …
我在树结构上使用递归 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) optimization ×10
sql-server ×5
postgresql ×3
cte ×2
index ×2
mysql ×2
performance ×2
innodb ×1
mysql-5.1 ×1
recursive ×1
view ×1