我正在构建一个 Web 应用程序(项目管理系统),并且在性能方面我一直对此感到疑惑。
我有一个问题表,里面有 12 个外键链接到各种其他表。其中,我需要加入其中的 8 个以从其他表中获取标题字段,以便记录在 Web 应用程序中有意义,但这意味着进行 8 个连接,这似乎非常多,尤其是因为我只是在拉入每个连接有 1 个字段。
现在我还被告知要使用自动递增的主键(除非分片是一个问题,在这种情况下我应该使用 GUID)出于永久性原因,但是使用 varchar(最大长度 32)性能有多糟糕?我的意思是这些表中的大多数可能不会有很多记录(其中大多数应该低于 20)。此外,如果我使用标题作为主键,我将不必在 95% 的时间内进行连接,因此对于 95% 的 sql,我什至会发生任何性能下降(我认为)。我能想到的唯一缺点是我的磁盘空间使用量会更高(但一天下来真的很重要)。
我使用查找表来代替枚举的原因是因为我需要最终用户通过应用程序本身来配置所有这些值。
使用 varchar 作为表的主键的缺点是什么,除非有很多记录?
更新 - 一些测试
所以我决定对这些东西做一些基本的测试。我有 100000 条记录,这些是基本查询:
基本 VARCHAR FK 查询
SELECT i.id, i.key, i.title, i.reporterUserUsername, i.assignedUserUsername, i.projectTitle,
i.ProjectComponentTitle, i.affectedProjectVersionTitle, i.originalFixedProjectVersionTitle,
i.fixedProjectVersionTitle, i.durationEstimate, i.storyPoints, i.dueDate,
i.issueSecurityLevelId, i.creatorUserUsername, i.createdTimestamp,
i.updatedTimestamp, i.issueTypeId, i.issueStatusId
FROM ProjectManagement.Issues i
Run Code Online (Sandbox Code Playgroud)
基础 INT FK 查询
SELECT i.id, i.key, i.title, ru.username as reporterUserUsername,
au.username as assignedUserUsername, p.title as projectTitle,
pc.title as …Run Code Online (Sandbox Code Playgroud) 我有一个查询目前平均需要 2500 毫秒才能完成。我的表很窄,但有 4400 万行。我有什么选择可以提高性能,或者这是否已经达到了最好的效果?
查询
SELECT TOP 1000 * FROM [CIA_WIZ].[dbo].[Heartbeats]
WHERE [DateEntered] BETWEEN '2011-08-30' and '2011-08-31';
Run Code Online (Sandbox Code Playgroud)
桌子
CREATE TABLE [dbo].[Heartbeats](
[ID] [int] IDENTITY(1,1) NOT NULL,
[DeviceID] [int] NOT NULL,
[IsPUp] [bit] NOT NULL,
[IsWebUp] [bit] NOT NULL,
[IsPingUp] [bit] NOT NULL,
[DateEntered] [datetime] NOT NULL,
CONSTRAINT [PK_Heartbeats] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
指数
CREATE NONCLUSTERED INDEX …Run Code Online (Sandbox Code Playgroud) 在我妻子的工作中,关于仅使用存储过程中临时表中的varchar(255)所有varchar字段存在争议。基本上,一个阵营希望使用 255,因为即使定义发生变化它也始终有效,而另一个阵营则希望坚持使用源表中的大小以提高潜在的性能。
表演营对吗?是否有其他影响?他们正在使用 SQL Server。
鉴于reddit 上的这个问题,我清理了查询以指出问题在查询中的位置。我首先使用逗号WHERE 1=1并使修改查询更容易,所以我的查询通常是这样结束的:
SELECT
C.CompanyName
,O.ShippedDate
,OD.UnitPrice
,P.ProductName
FROM
Customers as C
INNER JOIN Orders as O ON C.CustomerID = O.CustomerID
INNER JOIN [Order Details] as OD ON O.OrderID = OD.OrderID
INNER JOIN Products as P ON P.ProductID = OD.ProductID
Where 1=1
-- AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
And P.productname = 'TOFU'
Order By C.CompanyName
Run Code Online (Sandbox Code Playgroud)
有人基本上说1=1 通常是懒惰的,而且对性能不利。
鉴于我不想“过早优化” - 我确实想遵循良好的做法。我以前看过查询计划,但通常只是为了找出我可以添加(或调整)哪些索引以使我的查询运行得更快。
那么问题真的……会Where 1=1导致不好的事情发生吗?如果是这样,我怎么知道?
次要编辑:我也一直“假设”1=1会被优化,或者在最坏的情况下可以忽略不计。质疑一句口头禅永远不会有什么坏处,比如“Goto's are Evil”或“过早优化......”或其他假设的事实。不确定是否1=1 AND会实际影响查询计划。在子查询中呢?CTE的?手续?
除非需要,否则我不是要优化的人……但如果我正在做一些实际上“不好”的事情,我想尽量减少影响或在适用的情况下进行更改。
我将大型网站和数据库从旧服务器(Windows 2008 / SQL Server 2008 / 16 GB RAM / 2 x 2.5 GHz 四核 / SAS 磁盘)迁移到更新、更好的服务器(Windows 2008 R2 / SQL Server 2012 SP1 / 64 GB RAM / 2 x 2.1 GHz 16 核处理器 / SSD 磁盘)。
我分离了旧服务器上的数据库文件,将它们复制并附加到新服务器上。一切都很顺利。
之后,我将兼容级别更改为 110,更新统计信息,重建索引。
令我非常失望的是,我注意到大多数 sql 查询在新的 SQL 2012 服务器上比在旧的 SQL 2008 服务器上慢得多(慢 2-3-4 倍)。
例如,在一个包含大约 70 万条记录的表上,在旧服务器上查询索引需要大约 100 毫秒。在新服务器上,相同的查询大约需要 350 毫秒。
所有查询都会发生同样的情况。
我会很感激这里的一些帮助。让我知道要检查/验证的内容。因为我发现很难相信在具有更新 SQL Server 的更好服务器上,性能会更差。
更多细节:
内存设置为最大。
我有这个表和索引:
CREATE TABLE [dbo].[Answer_Details_23](
[ID] [int] IDENTITY(1,1) NOT NULL,
[UserID] [int] NOT …Run Code Online (Sandbox Code Playgroud) 在查看需要很长时间执行的存储过程列表时,其中一个会引起最多的等待。然而,大部分等待 (81%) 是 ASYNC_NETWORK_IO,我知道原因:存储过程传输大约 400 MB 的信息。
在文档中,它指出 ASYNC_NETWORK_IO 的原因是客户端无法跟上数据的洪流,这可能是真的。我不确定如何让客户端跟上,因为它所做的只是通过 ADO.NET 调用存储过程,然后只处理数据集。
因此,鉴于此信息,我是否应该担心此过程的 ASYNC_NETWORK_IO 等待类型?它实际上对服务器性能有影响吗?
补充资料:
performance sql-server-2005 sql-server stored-procedures wait-types
redis 服务器 v2.8.4 在 Ubuntu 14.04 VPS 上运行,具有 8 GB RAM 和 16 GB 交换空间(在 SSD 上)。但是htop显示redis单独占用22.4 G内存!
redis-server最终因为内存不足而崩溃。Mem并且Swp两者都命中 100% 然后redis-server与其他服务一起被杀死。
来自dmesg:
[165578.047682] Out of memory: Kill process 10155 (redis-server) score 834 or sacrifice child
[165578.047896] Killed process 10155 (redis-server) total-vm:31038376kB, anon-rss:5636092kB, file-rss:0kB
Run Code Online (Sandbox Code Playgroud)
redis-server从 OOM 崩溃或service redis-server force-reload导致内存使用量下降到 <100MB 的情况下重新启动。
问题:为什么会redis-server占用越来越多的内存直到崩溃?我们怎样才能防止这种情况发生?
设置是不是真的maxmemory不行,因为一旦redis达到maxmemory限制,它就会开始删除数据?

重启 redis-server 后 …
我们拥有庞大的生产数据库,其大小约为 300GB。有什么方法可以提高删除查询的性能?现在删除速度在每分钟1-10k之间,对我们来说非常慢。
我最近遇到了这个问题,在网上找不到任何讨论。
下面的查询
DECLARE @S VARCHAR(1) = '';
WITH T
AS (SELECT name + @S AS name2,
*
FROM master..spt_values)
SELECT *
FROM T T1
INNER JOIN T T2
ON T1.name2 = T2.name2;
Run Code Online (Sandbox Code Playgroud)
总是得到一个嵌套循环计划

尝试使用INNER HASH JOIN或INNER MERGE JOIN提示强制问题会产生以下错误。
由于此查询中定义的提示,查询处理器无法生成查询计划。在不指定任何提示且不使用 SET FORCEPLAN 的情况下重新提交查询。
我找到了一种允许使用散列或合并连接的解决方法 - 将变量包装在聚合中。生成的计划成本显着降低(19.2025 与 0.261987)
DECLARE @S2 VARCHAR(1) = '';
WITH T
AS (SELECT name + (SELECT MAX(@S2)) AS name2,
*
FROM spt_values)
SELECT *
FROM T T1
INNER JOIN T T2 …Run Code Online (Sandbox Code Playgroud) 我有一个查询,它连接了几个表并且执行得非常糟糕 - 行估计偏离了(1000 次)并且选择了嵌套循环连接,从而导致多个表扫描。查询的形状相当简单,看起来像这样:
SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id
WHERE t4.id = some_GUID
Run Code Online (Sandbox Code Playgroud)
玩弄查询时,我注意到当我提示它对其中一个连接使用合并连接时,它的运行速度要快很多倍。这我可以理解 - 合并连接是连接数据的更好选择,但 SQL Server 只是没有正确选择嵌套循环。
我不完全理解的是为什么这个连接提示会改变所有计划运营商的所有估计?通过阅读不同的文章和书籍,我假设基数估计是在构建计划之前执行的,因此使用提示不会改变估计,而是明确告诉 SQL Server 使用特定的物理连接实现。
然而,我看到的是合并提示使所有估计变得非常完美。为什么会发生这种情况,是否有任何通用技术可以使查询优化器在没有提示的情况下做出更好的估计 - 考虑到统计数据显然允许这样做?
UPD:匿名执行计划可以在这里找到:https ://www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan?dl =0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl =0
我使用 TF 3604、9292 和 9204 检查了这两个查询使用的统计数据,它们是相同的。然而,被扫描/搜索的索引在查询之间是不同的。
除此之外,我尝试运行查询OPTION (FORCE ORDER)- 它比使用合并联接运行得更快,为每个联接选择 HASH MATCH。
performance sql-server optimization t-sql performance-tuning
performance ×10
sql-server ×7
optimization ×4
datatypes ×1
innodb ×1
memory ×1
mysql ×1
nosql ×1
primary-key ×1
redis ×1
t-sql ×1
ubuntu ×1
wait-types ×1