我有一个非常基本的表:
CREATE TABLE [obj_local] (
[obj_id] INT NOT NULL,
[value] NVARCHAR (1000) NOT NULL
);
Run Code Online (Sandbox Code Playgroud)
这个表存储了很多数据,我需要在value列中搜索一个字符序列:
SELECT [obj_id] FROM [obj_local] WHERE [value] LIKE '%{substring}%'
Run Code Online (Sandbox Code Playgroud)
这是非常缓慢的。我的理解是,由于两边的通配符,索引对我没有帮助,全文索引也对我没有帮助,因为我不是在搜索标记(单词)。
我可以做些什么来优化此搜索?
使用 Postgres 9.4,我经常执行以下查询:
SELECT DISTINCT ON(recipient) * FROM messages
LEFT JOIN identities ON messages.recipient = identities.name
WHERE timestamp BETWEEN timeA AND timeB
ORDER BY recipient, timestamp DESC;
Run Code Online (Sandbox Code Playgroud)
所以我决定创建一个视图:
CREATE VIEW myView AS SELECT DISTINCT ON(recipient) * FROM messages
LEFT JOIN identities ON messages.recipient = identities.name
ORDER BY recipient, timestamp DESC;
Run Code Online (Sandbox Code Playgroud)
我刚刚意识到,如果我查询我的观点,就像SELECT * FROM myView WHERE timestamp BETWEEN timeA AND timeB我的表现要差很多一样。
这样EXPLAIN ANALYZE两个问题,我发现了原因是,在第二种情况下,数据库带来了所有记录,请问左连接,然后应用WHERE条款。换句话说,WHERE子句不会被下推到视图的查询中。我还尝试ORDER BY从视图中删除,但数据库仍然LEFT JOIN对完整数据而不是过滤集执行。
这种行为的原因是什么?有没有办法在使用视图时获得可比较的性能?
我在 MySQL 中有一个名为 的表,messages如下所示:
id (primary key) | description | created_at(timestamp)
Run Code Online (Sandbox Code Playgroud)
该表应该保存我的应用程序用户之间的聊天消息。因此,对它的写操作次数会很高。
该应用程序有一个 API,可返回两个时间戳之间的所有消息。这个查询也很常见,但少于写操作的次数。
我用 100 个并发连接和该表中的大约 15000 行运行 mysqlslap,总时间约为 8.6 秒。
然后我在 上添加了一个二级索引created_at,希望在两次搜索之间在更短的时间内获得结果,但是对于相同的输入,我增加了 0.3 秒。
为什么我没有看到显着的性能提升?
编辑:
这是我的桌子的样子:
DROP TABLE IF EXISTS `mssg`;
CREATE TABLE `mssg` (
`id` INTEGER NULL AUTO_INCREMENT DEFAULT NULL,
`body` MEDIUMTEXT NULL DEFAULT NULL,
`length` VARCHAR NULL DEFAULT NULL,
`created_at` TIMESTAMP NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
Run Code Online (Sandbox Code Playgroud)
这就是我添加索引的方式:
ALTER TABLE testalter_tbl ADD INDEX (created_at);
Run Code Online (Sandbox Code Playgroud)
通常,select 语句会返回大约 150 到 350 条消息
通常我必须在获取其他非相关行的查询中返回某些行的计数。
例如一个表用户一个表评论和一个表图片
User:
id
nickname
Review:
id
to_user_id
from_user_id
rating
Picture:
id:
user_id
url
Run Code Online (Sandbox Code Playgroud)
假设我想在一个查询中检索“给定”userId 的所有图片 url 的昵称以及评论该用户的人数。
我认为在执行此查询时的第一种也是简单的方法是:
SELECT
u.nickname
(SELECT count(*) FROM review WHERE to_user_id = u.id) as reviewCount,
p.url
FROM user
LEFT JOIN picture ON p.user_id = u.id
WHERE
u.id = 1
Run Code Online (Sandbox Code Playgroud)
这样做的另一种方法是没有那个子选择并通过在正确的 user_id 上加入评论表
SELECT
u.nickname,
r.reviewCount,
p.url
FROM user u
LEFT JOIN (
SELECT to_user_id, count(*) reviewCount FROM review GROUP BY to_user_id
) r ON r.to_user_id = u.id
LEFT JOIN picture ON p.user_id …Run Code Online (Sandbox Code Playgroud) SELECT [BusinessEntityID],[NationalIDNumber],[LoginID],[OrganizationNode]
FROM [AdventureWorks2014].[HumanResources].[Employee]
where BusinessEntityID = 5
Run Code Online (Sandbox Code Playgroud)
在实际执行计划中执行查询后,我得到了 SQL Server 调用的 convert_implicit() 函数。
SELECT [BusinessEntityID],[NationalIDNumber],[LoginID],[OrganizationNode]
FROM [AdventureWorks2014].[HumanResources].[Employee]
where BusinessEntityID = convert(int,5)
Run Code Online (Sandbox Code Playgroud)
显然,当我将标量值显式转换为整数类型时,不会调用 convert_implicit() 函数。有什么方法可以避免在不使用显式转换的情况下对标量 int 值进行隐式转换。另外我想知道隐式转换、显式转换和根本没有转换之间的性能差异。
我试图用大量虚拟数据填充表,以便我可以进行优化等。
我有以下几点:
WHILE @RowCount < 3000000
BEGIN
SELECT @Random = ROUND(@Upper * RAND(), 0)
INSERT INTO [dbo].[Test]
([Id]
,[OtherKey]
,[Description])
VALUES
(@RowCount
,@Random
,CAST(@Random AS VARCHAR(max)))
SET @RowCount = @RowCount + 1
END
Run Code Online (Sandbox Code Playgroud)
然而,这似乎很慢。
有没有更好的方法来自动将半随机行加载到数据库表中?
这个似乎很快:
USE [Test]
GO
/****** Object: Table [dbo].[Test] Script Date: 17/10/2016 21:22:39 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
USE [Test]
GO
CREATE TABLE [dbo].[Test](
[Id] [int] NOT NULL,
[OtherKey] [int] NOT NULL,
[Description] [varchar](max) NOT NULL,
[Time] [datetime] NOT NULL
) …Run Code Online (Sandbox Code Playgroud) 我在 MS-SQL 中有下表:
CREATE TABLE [dbo].[dbip_locations](
[ip_from] [bigint] NOT NULL,
[ip_to] [bigint] NOT NULL,
[country_code] [nvarchar](64) NOT NULL,
[region_name] [nvarchar](128) NOT NULL,
[city_name] [nvarchar](128) NOT NULL,
[latitude] [float] NOT NULL,
[longitude] [float] NOT NULL
)
Run Code Online (Sandbox Code Playgroud)
ip_from 和 ip_to 列是根据 ipv4 地址计算的,如下所示:
return (
convert(bigint, parsename(@ip, 1)) +
convert(bigint, parsename(@ip, 2)) * convert(bigint, 256) +
convert(bigint, parsename(@ip, 3)) * convert(bigint, 65536) +
convert(bigint, parsename(@ip, 4)) * convert(bigint, 16777216)
)
Run Code Online (Sandbox Code Playgroud)
然后,我使用使用上述计算转换为 bigint 的 ipv4 地址来搜索 ip 地址位于 ip_from 和 ip_to 列之间的行。
我总是会找到一行,虽然它不是由模式强制执行的,但这是数据中的现实。 …
index sql-server optimization clustered-index nonclustered-index
我有一个查询,我想从 date_ added 列排序的表数据集中获取前几行。排序依据的列被索引,所以这个表的基本版本非常快:
SELECT datasets.id FROM datasets ORDER BY date_added LIMIT 25
Run Code Online (Sandbox Code Playgroud)
"Limit (cost=0.28..6.48 rows=25 width=12) (actual time=0.040..0.092 rows=25 loops=1)"
" -> Index Scan using datasets_date_added_idx2 on datasets (cost=0.28..1244.19 rows=5016 width=12) (actual time=0.037..0.086 rows=25 loops=1)"
"Planning time: 0.484 ms"
"Execution time: 0.139 ms"
Run Code Online (Sandbox Code Playgroud)
但是一旦我使查询变得更复杂,我就会遇到问题。我想加入另一个表示多对多关系的表,并将结果聚合在一个数组列中。为此,我需要添加一个 GROUP BY id 子句:
SELECT datasets.id FROM datasets GROUP BY datasets.id ORDER BY date_added LIMIT 25
Run Code Online (Sandbox Code Playgroud)
"Limit (cost=551.41..551.47 rows=25 width=12) (actual time=9.926..9.931 rows=25 loops=1)"
" -> Sort (cost=551.41..563.95 rows=5016 width=12) (actual time=9.924..9.926 rows=25 loops=1)"
" …Run Code Online (Sandbox Code Playgroud) postgresql performance optimization postgresql-9.5 query-performance
在阅读了大量有关 SQL Server 中临时表和表变量之间差异的信息后,我正在尝试从主要使用临时表切换到主要使用表变量。(它们似乎更适合我通常使用的查询类型。)
在这些查询中,表包含驱动查找过程的唯一标识符。在使用临时表时,我的习惯是包含一个PRIMARY KEY约束,以便查询优化器知道它不会看到任何重复项。但是,鉴于优化器(在大多数情况下,对于我的查询)假定表变量仅包含单行*,根据定义这是唯一的,如果存在PRIMARY KEY约束,查询优化器是否会做出任何不同的选择?
* 从技术上讲,它假定没有行,但将零替换为一。(因为零与估计过程的其余部分的交互非常差。)但这也取决于在编译查询时是否填充了表变量。这里有一些背景信息:SQL Server 中的临时表和表变量有什么区别?.
我目前正在使用 SQL Server 2014,但我很好奇新版本的行为是否发生变化。
正如已经指出的那样,PRIMARY KEY约束带有聚集索引,它为查询优化器提供了更多关于如何从表变量中获取数据的选择。我意识到了这一点,并考虑了查询计划的其余部分。但是在试图澄清我的问题之后,我决定我试图提出的问题太广泛了,可能特别针对我的极端情况。(不过是对半万亿行表的导航类型查询,期望达到亚秒级性能。)所以我将保持我的问题不变。
在处理以下查询以回答此问题时:
有以下表格:
CREATE TABLE [dbo].[#foo] (
[creation] DATETIME NOT NULL,
[value] MONEY NULL,
[DT] AS (CONVERT([date],[CREATION])) PERSISTED)
-- add a clustered index on the dt column
CREATE CLUSTERED INDEX CI_FOO ON #FOO(DT)
GO
Run Code Online (Sandbox Code Playgroud)
和另一个加入表:
create table #bar (dt date primary key clustered)
go
Run Code Online (Sandbox Code Playgroud)
但是在运行以下查询时:
WITH RADHE AS (
SELECT THE_ROW=ROW_NUMBER() OVER(PARTITION BY B.DT ORDER BY B.DT),
THE_DATE=B.dt,
THE_NUMBER_OF_RECORDS_ON_THIS_DAY=CASE WHEN F.DT IS NULL THEN 0 ELSE COUNT(*) OVER (PARTITION BY F.DT ) END ,
THE_TOTAL_VALUE_FOR_THE_DAY=COALESCE(SUM(F.VALUE) OVER (PARTITION BY …Run Code Online (Sandbox Code Playgroud) performance sql-server optimization execution-plan sort-operator query-performance
optimization ×10
sql-server ×6
performance ×5
index ×2
mysql ×2
postgresql ×2
bulk-insert ×1
mysql-5.7 ×1
view ×1