AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 341466
Accepted
user1664043
user1664043
Asked: 2024-08-07 01:00:50 +0800 CST2024-08-07 01:00:50 +0800 CST 2024-08-07 01:00:50 +0800 CST

CLR 1 行表值函数还是用户定义类型?

  • 772

我正在使用网络蜘蛛数据的数据库,并尝试通过 CLR 利用 C# Uri 类来帮助进行流量分析。

我的第一步是创建一个 CLR 表值函数(仅返回 1 行)并 CROSS APPLY 将 URL 分解为组件部分以供审查,但我发现添加 CROSS APPLY 确实会减慢查询速度(例如,对数据库使用 LIKE 进行查询可能需要 5-8 分钟,但 CROSS APPLY 和查看主机值需要 45 分钟)

我想知道将 Uri 接口实现为用户定义类型并将其用于查询是否会更快?我没有做过很多用户定义类型,但我认为知道只有一个响应对象可能会减轻 Sql Server 中的一些开销。UDT 在查询中的表现会更好吗?

我的 tvf 实现目前如下所示:

    [SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true, IsPrecise = true, Name = "ufn_UrlParts", SystemDataAccess = SystemDataAccessKind.None, FillRowMethodName = "GetUrlParts")]
    public static IEnumerable UrlParts(SqlString input)
    {
        if (!input.IsNull && Uri.TryCreate(input.Value, UriKind.Absolute, out Uri url) && url.Valid(false))
            yield return url;
        yield break;
    }

    private static void GetUrlParts(object input, out string scheme, out string userinfo, out string host, out int hostType, out int port, out bool isdefaultPort, out string path, out string query)
    {
        Uri u = input as Uri;
        scheme = u?.Scheme;
        userinfo = u?.UserInfo;
        host = u?.Host;
        hostType = (int)(u?.HostNameType ?? UriHostNameType.Unknown);
        port = u?.Port ?? 0;
        isdefaultPort = u?.IsDefaultPort ?? false;
        path = u?.AbsolutePath;
        query = u?.Query;
    }
sql-server
  • 2 2 个回答
  • 52 Views

2 个回答

  • Voted
  1. Steve
    2024-08-07T04:04:25+08:002024-08-07T04:04:25+08:00

    如果可能的话,我的第一种方法是尝试编写一个纯 SQL 解决方案来解析主机名。

    但是,如果您必须使用 DotNet Uri 类(例如,因为它在解析任意 URI 时非常全面和稳健),那么您可能会发现,与其为每一行从 SQL 调用一个 CLR 函数,不如编写一个 CLR 函数/存储过程,当对整个批次调用一次(没有参数)时,回调数据库以批量获取原始数据,然后在 CLR 函数/过程中完全循环处理它,最后返回/存储整个结果集。

    此外,我不会排除这样一种可能性,即相对低效和缓慢(与 LIKE 过滤器相比)是由于使用 Uri 类本身以及将原始字符串解析为完全结构化的 Uri 的巨大成本造成的。您是否尝试过独立对 Uri 类进行基准测试?

    • 1
  2. Best Answer
    user1664043
    2024-08-09T03:46:38+08:002024-08-09T03:46:38+08:00

    我继续努力,构建了一个基本的 UDT,实现与类相同的接口,并运行了一些测试。

    事实证明,UDT 实现的运行速度比 clr 函数快 30-40%。

    我使用 Include Plan 运行了它们。执行相同操作但使用函数而非 UDT 的查询的计划具有嵌套连接的函数,而 UDT 是两个计算标量节点。这些计划认为 udt 查询将占用 3%,而函数查询将占用 97%。如果真是这样,我会很高兴,但 CLR 对计划估算器来说是一个黑匣子。

        [Serializable]
    [SqlUserDefinedType(Format.UserDefined, IsByteOrdered = false, MaxByteSize = -1)]
    public struct Url : INullable, IBinarySerialize
    {
        private static readonly Url _null = new Url { is_Null = true };
        private bool is_Null;
        private Uri _url;
    
        public bool IsNull => is_Null;
    
        public static Url Null
        {
            get => _null;
        }
    
        public override string ToString()
        {   // Since InvokeIfReceiverIsNull defaults to 'true' this test is unnecessary if Url is only being called from SQL.  
            if (this.IsNull)
                return "NULL";
            return _url.ToString();
        }
    
        [SqlMethod(OnNullCall = false)]
        public static Url Parse(SqlString input)
        {
            if (!input.IsNull && Uri.TryCreate(input.Value, UriKind.Absolute, out Uri url) && url.Valid(false))
                return new Url { _url = url };
            return _null;
        }
    
        public void Read(BinaryReader r)
        {
            string u = r.ReadString();
            if (!String.IsNullOrEmpty(u) && Uri.TryCreate(u, UriKind.Absolute, out Uri url) && url.Valid(false))
                _url = url;
            else
                is_Null = true;
        }
    
        public void Write(BinaryWriter w)
        {
            w.Write(!is_Null ? _url.ToString() : "");
        }
    
        public string Scheme { get => this.is_Null ? null : this._url.Scheme; }
    
        public string UserInfo { get => this.is_Null ? null : this._url.UserInfo; }
    
        public string Host { get => this.is_Null ? null : this._url.Host; }
    
        public int? HostType { get => this.is_Null ? (int?)null : (int)this._url.HostNameType; }
    
        public int? Port { get => this.is_Null ? (int?)null : this._url.Port; }
    
        public bool? IsDefaultPort { get => this.is_Null ? (bool?)null : this._url.IsDefaultPort; }
    
        public string Path { get => this.is_Null ? null : this._url.AbsolutePath; }
    
        public string Query { get => this.is_Null ? null : this._url.Query; }
    }
    
    • 0

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve