সমান্তরালভাবে চালানোর জন্য আমি কি এই ক্যোয়ারীটি রিফ্যাক্টর করতে পারি?


12

আমার একটি ক্যোয়ারী রয়েছে যা আমাদের সার্ভারে চালাতে প্রায় 3 ঘন্টা সময় নেয় - এবং এটি সমান্তরাল প্রক্রিয়াজাতকরণের সুবিধা নেয় না। (প্রায় 1.15 মিলিয়ন রেকর্ড ইন dbo.Deidentified, 300 রেকর্ড ইন dbo.NamesMultiWord)। সার্ভারটিতে 8 টি কোরের অ্যাক্সেস রয়েছে।

  UPDATE dbo.Deidentified 
     WITH (TABLOCK)
  SET IndexedXml = dbo.ReplaceMultiWord(IndexedXml),
      DE461 = dbo.ReplaceMultiWord(DE461),
      DE87 = dbo.ReplaceMultiWord(DE87),
      DE15 = dbo.ReplaceMultiWord(DE15)
  WHERE InProcess = 1;

এবং ReplaceMultiwordএকটি পদ্ধতি হিসাবে সংজ্ঞায়িত:

SELECT @body = REPLACE(@body,Names,Replacement)
 FROM dbo.NamesMultiWord
 ORDER BY [WordLength] DESC
RETURN @body --NVARCHAR(MAX)

ReplaceMultiwordসমান্তরাল পরিকল্পনা গঠনের প্রতিরোধ করার আহ্বান কি ? সমান্তরালতার অনুমতি দেওয়ার জন্য কি এটি পুনর্লিখনের কোনও উপায় আছে?

ReplaceMultiword অবতরণ ক্রমে চলে কারণ কিছু প্রতিস্থাপন অন্যদের সংক্ষিপ্ত সংস্করণ, এবং আমি চাই দীর্ঘতম ম্যাচটি সফল হোক।

উদাহরণস্বরূপ, 'জর্জ ওয়াশিংটন বিশ্ববিদ্যালয়' এবং অন্যটি 'ওয়াশিংটন বিশ্ববিদ্যালয়' থেকে থাকতে পারে। যদি 'ওয়াশিংটন বিশ্ববিদ্যালয়' ম্যাচটি প্রথম হয়, তবে 'জর্জ' পিছনে ফেলে রাখা হত।

জিজ্ঞাসা পরিকল্পনা

প্রযুক্তিগতভাবে আমি সিএলআর ব্যবহার করতে পারি, কীভাবে এটি করা যায় তার সাথে আমি কেবল পরিচিত নই।


3
চলক কার্যভার কেবলমাত্র একটি একক সারির জন্য আচরণকে সংজ্ঞায়িত করেছে। SELECT @var = REPLACE ... ORDER BYনির্মাণ কাজ নিশ্চিত করা হয় না হিসাবে আপনি আশা। উদাহরণ আইটেম সংযুক্ত করুন (মাইক্রোসফ্ট থেকে প্রতিক্রিয়া দেখুন)। সুতরাং, এসকিউএলসিএলআর স্যুইচ করাতে সঠিক ফলাফলের গ্যারান্টি যুক্ত করার অতিরিক্ত সুবিধা রয়েছে যা সর্বদা দুর্দান্ত।
পল হোয়াইট 9

উত্তর:


11

ইউডিএফ সমান্তরালতা রোধ করছে। এটি সেই স্পুলের কারণও বটে।

আপনি নিজের অনুসন্ধান এবং প্রতিস্থাপনের জন্য সিএলআর এবং একটি সংকলিত রেজেক্স ব্যবহার করতে পারেন। এটি প্রয়োজনীয় বৈশিষ্ট্য উপস্থিত থাকাকালীন সমান্তরালতা অবরুদ্ধ করে না এবং REPLACEফাংশন কল প্রতি 300 টিএসকিউএল ক্রিয়াকলাপ সম্পাদনের চেয়ে উল্লেখযোগ্যভাবে দ্রুততর হবে ।

উদাহরণ কোড নীচে।

DECLARE @X XML = 
(
    SELECT Names AS [@find],
           Replacement  AS [@replace]
    FROM  dbo.NamesMultiWord 
    ORDER BY [WordLength] DESC
    FOR XML PATH('x'), ROOT('spec')
);

UPDATE dbo.Deidentified WITH (TABLOCK)
SET    IndexedXml = dbo.ReplaceMultiWord(IndexedXml, @X),
       DE461 = dbo.ReplaceMultiWord(DE461, @X),
       DE87 = dbo.ReplaceMultiWord(DE87, @X),
       DE15 = dbo.ReplaceMultiWord(DE15, @X)
WHERE  InProcess = 1; 

এটি নীচের মতো সিএলআর ইউডিএফের অস্তিত্বের উপর নির্ভর করে (এর DataAccessKind.Noneঅর্থ হ'ল হ্যালোইন সুরক্ষার জন্য স্পুলটি অদৃশ্য হওয়ার পাশাপাশি এটির প্রয়োজন নেই কারণ এটি লক্ষ্য সারণিতে অ্যাক্সেস না করে)।

using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Xml;

public partial class UserDefinedFunctions
{
    //TODO: Concurrency?
    private static readonly Dictionary<string, ReplaceSpecification> cachedSpecs = 
                        new Dictionary<string, ReplaceSpecification>();

    [SqlFunction(IsDeterministic = true,
                 IsPrecise = true,
                 DataAccess = DataAccessKind.None,
                 SystemDataAccess = SystemDataAccessKind.None)]
    public static SqlString ReplaceMultiWord(SqlString inputString, SqlXml replacementSpec)
    {
        //TODO: Implement something to drop things from the cache and use a shorter key.
        string s = replacementSpec.Value;
        ReplaceSpecification rs;

        if (!cachedSpecs.TryGetValue(s, out rs))
        {
            var doc = new XmlDocument();
            doc.LoadXml(s);
            rs = new ReplaceSpecification(doc);
            cachedSpecs[s] = rs;
        }

        string result = rs.GetResult(inputString.ToString());
        return new SqlString(result);
    }


    internal class ReplaceSpecification
    {
        internal ReplaceSpecification(XmlDocument doc)
        {
            Replacements = new Dictionary<string, string>();

            XmlElement root = doc.DocumentElement;
            XmlNodeList nodes = root.SelectNodes("x");

            string pattern = null;
            foreach (XmlNode node in nodes)
            {
                if (pattern != null)
                    pattern = pattern + "|";

                string find = node.Attributes["find"].Value.ToLowerInvariant();
                string replace = node.Attributes["replace"].Value;
                 //TODO: Escape any special characters in the regex syntax
                pattern = pattern + find;
                Replacements[find] = replace;
            }

            if (pattern != null)
            {
                pattern = "(?:" + pattern + ")";
                Regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled);
            }


        }
        private Regex Regex { get; set; }

        private Dictionary<string, string> Replacements { get; set; }


        internal string GetResult(string inputString)
        {
            if (Regex == null)
                return inputString;

            return Regex.Replace(inputString,
                                 (Match m) =>
                                 {
                                     string s;
                                     if (Replacements.TryGetValue(m.Value.ToLowerInvariant(), out s))
                                     {
                                         return s;
                                     }
                                     else
                                     {
                                         throw new Exception("Missing replacement definition for " + m.Value);
                                     }
                                 });
        }
    }
}

আমি শুধু এটি বেঞ্চমার্ক। প্রত্যেকের জন্য একই টেবিল এবং সামগ্রীগুলি ব্যবহার করে, সিএলআর 1,174,731 সারিগুলি প্রক্রিয়া করতে 3: 03.51 নিয়েছে এবং ইউডিএফ 3: 16.21 নিয়েছে। এটি সময় বাঁচায়। আমার নৈমিত্তিক পড়াতে, দেখে মনে হচ্ছে যে এসকিউএল সার্ভার আপডেটের প্রশ্নের সমান্তরাল করতে তত্পর।
rsjaffe

@rsjaffe হতাশ। আমি এর চেয়ে আরও ভাল ফলাফলের আশা করতাম। জড়িত তথ্য আকার কি? (সমস্ত প্রভাবিত কলামগুলির ডেটার দৈর্ঘ্যের যোগফল)
মার্টিন স্মিথ

608 মিলিয়ন অক্ষর, 1.216 গিগাবাইট, ফর্ম্যাটটি এনভিচারচার। আমি whereরেগেক্সের সাথে ম্যাচের জন্য একটি পরীক্ষা ব্যবহার করে একটি ধারা যুক্ত করার কথা ভাবছিলাম , কারণ বেশিরভাগ লেখক অপ্রয়োজনীয় - 'হিট' এর ঘনত্ব কম হওয়া উচিত, তবে আমার সি # দক্ষতা (আমি সি ++ লোক) না আমাকে সেখানে নিয়ে যাও আমি এমন পদ্ধতির লাইন ধরে ভাবছিলাম public static SqlBoolean CanReplaceMultiWord(SqlString inputString, SqlXml replacementSpec)যা ফিরে আসবে return Regex.IsMatch(inputString.ToString()); তবে আমি সেই রিটার্নের বিবৃতিতে ত্রুটি পেয়েছি যেমন `System.Text.RegularExpressions.Eegex একটি প্রকার তবে এটি ভেরিয়েবলের মতো ব্যবহৃত হয়।
rsjaffe

4

নীচের লাইন : ধারাটিতে মানদণ্ড যুক্ত করা WHEREএবং ক্যোয়ারিকে চারটি পৃথক ক্যোয়ারিতে বিভক্ত করা, প্রতিটি ক্ষেত্রের জন্য একটি এসকিউএল সার্ভারকে একটি সমান্তরাল পরিকল্পনা সরবরাহ করার অনুমতি দিয়েছিল এবং ক্লোজে অতিরিক্ত পরীক্ষা ছাড়াই কোয়েরিটি 4X তত দ্রুত চালানো হয়েছিল WHERE। পরীক্ষাগুলি ব্যতীত ক্যোয়ারিকে চার ভাগে বিভক্ত করা তা করেনি। উভয়ই প্রশ্নগুলি বিভক্ত না করে পরীক্ষা যোগ করেনি। পরীক্ষাটি অনুকূল করা মোট রান সময়কে 3 মিনিটে (মূল 3 ঘন্টা থেকে) হ্রাস করেছে।

আমার মূল ইউডিএফটি ১,১,73, r৩১ টি সারি প্রসেস করতে 3 ঘন্টা 16 মিনিট সময় নিয়েছিল, যার মধ্যে 1.216 গিগাবাইট এনভারচার ডেটা পরীক্ষা করা হয়েছিল। মার্টিন স্মিথ তার উত্তরে প্রদত্ত সিএলআর ব্যবহার করে কার্যকর করার পরিকল্পনাটি এখনও সমান্তরাল হয়নি এবং এই কার্যটিতে 3 ঘন্টা 5 মিনিট সময় লেগেছিল। সিএলআর, কার্যকর করার পরিকল্পনা সমান্তরাল নয়

এই WHEREমানদণ্ডটি UPDATEসমান্তরাল দিকে এগিয়ে যেতে সহায়তা করতে পারে তা পড়ে, আমি নিম্নলিখিতগুলি করেছি। ফিল্ডটির রেজেসের সাথে কোনও মিল আছে কিনা তা দেখতে আমি সিএলআর মডিউলে একটি ফাংশন যুক্ত করেছি:

[SqlFunction(IsDeterministic = true,
         IsPrecise = true,
         DataAccess = DataAccessKind.None,
         SystemDataAccess = SystemDataAccessKind.None)]
public static SqlBoolean CanReplaceMultiWord(SqlString inputString, SqlXml replacementSpec)
{
    string s = replacementSpec.Value;
    ReplaceSpecification rs;
    if (!cachedSpecs.TryGetValue(s, out rs))
    {
        var doc = new XmlDocument();
        doc.LoadXml(s);
        rs = new ReplaceSpecification(doc);
        cachedSpecs[s] = rs;
    }
    return rs.IsMatch(inputString.ToString());
}

এবং, ইন internal class ReplaceSpecification, আমি রেজেক্সের বিরুদ্ধে পরীক্ষা চালানোর জন্য কোডটি যুক্ত করেছি

    internal bool IsMatch(string inputString)
    {
        if (Regex == null)
            return false;
        return Regex.IsMatch(inputString);
    }

যদি সমস্ত ক্ষেত্র একক বিবৃতিতে পরীক্ষা করা হয়, এসকিউএল সার্ভার কাজের সমান্তরাল করে না

UPDATE dbo.DeidentifiedTest
SET IndexedXml = dbo.ReplaceMultiWord(IndexedXml, @X),
    DE461 = dbo.ReplaceMultiWord(DE461, @X),
    DE87 = dbo.ReplaceMultiWord(DE87, @X),
    DE15 = dbo.ReplaceMultiWord(DE15, @X)
WHERE InProcess = 1
    AND (dbo.CanReplaceMultiWord(IndexedXml, @X) = 1
    OR DE15 = dbo.ReplaceMultiWord(DE15, @X)
    OR dbo.CanReplaceMultiWord(DE87, @X) = 1
    OR dbo.CanReplaceMultiWord(DE15, @X) = 1);

4/2 ঘন্টা ধরে কার্যকর করার সময় এবং এখনও চলছে। হত্যা পরিকল্পনা: টেস্ট যুক্ত, একক বিবৃতি

যাইহোক, ক্ষেত্রগুলি পৃথক বিবৃতিতে পৃথক হলে একটি সমান্তরাল কাজের পরিকল্পনা ব্যবহৃত হয়, এবং আমার সিপিইউ ব্যবহার সমান্তরাল পরিকল্পনার সাথে সিরিয়াল পরিকল্পনার 12% থেকে 100% হয় সমান্তরাল পরিকল্পনা (8 কোর) এর সাথে।

UPDATE dbo.DeidentifiedTest
SET IndexedXml = dbo.ReplaceMultiWord(IndexedXml, @X)
WHERE InProcess = 1
    AND dbo.CanReplaceMultiWord(IndexedXml, @X) = 1;

UPDATE dbo.DeidentifiedTest
SET DE461 = dbo.ReplaceMultiWord(DE461, @X)
WHERE InProcess = 1
    AND dbo.CanReplaceMultiWord(DE461, @X) = 1;

UPDATE dbo.DeidentifiedTest
SET DE87 = dbo.ReplaceMultiWord(DE87, @X)
WHERE InProcess = 1
    AND dbo.CanReplaceMultiWord(DE87, @X) = 1;

UPDATE dbo.DeidentifiedTest
SET DE15 = dbo.ReplaceMultiWord(DE15, @X)
WHERE InProcess = 1
    AND dbo.CanReplaceMultiWord(DE15, @X) = 1;

46 মিনিট কার্যকর করার সময়। সারি পরিসংখ্যান দেখিয়েছে যে প্রায় 0.5% রেকর্ডটিতে কমপক্ষে একটি রেজেক্স ম্যাচ ছিল। হত্যা পরিকল্পনা: এখানে চিত্র বর্ণনা লিখুন

সময়, প্রধান টানা সময় ছিল WHEREধারা। আমি তারপর Regex পরীক্ষা প্রতিস্থাপিত WHEREসঙ্গে দফা Aho-Corasick অ্যালগরিদম একটি CLR হিসাবে প্রয়োগ করা। এটি মোট সময়টি 3 মিনিট 6 সেকেন্ডে হ্রাস করেছে।

এটির জন্য নিম্নলিখিত পরিবর্তনগুলি দরকার। আহো-করাসিক অ্যালগরিদমের জন্য সমাবেশ এবং ফাংশনগুলি লোড করুন। WHEREধারাটি পরিবর্তন করুন

WHERE  InProcess = 1 AND dbo.ContainsWordsByObject(ISNULL(FieldBeingTestedGoesHere,'x'), @ac) = 1; 

এবং প্রথমটির আগে নিম্নলিখিতগুলি যুক্ত করুন UPDATE

DECLARE @ac NVARCHAR(32);
SET @ac = dbo.CreateAhoCorasick(
  (SELECT NAMES FROM dbo.NamesMultiWord FOR XML RAW, root('root')),
  'en-us:i'
);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.