COALESCE ব্যবহার করে অবিচলিত কলামে আইডেন্টিটি থেকে প্রাথমিক কী পরিবর্তন করা হচ্ছে


10

আমাদের একচেটিয়া ডাটাবেস থেকে অ্যাপ্লিকেশনটি ডিকুয়াল করার প্রয়াসে, আমরা বিভিন্ন টেবিলের INT পরিচয় কলামগুলি একটি পৃথক গণিত কলামে COALESCE ব্যবহার করার পরিবর্তনের চেষ্টা করেছি। মূলত, আমাদের ডিকপলড অ্যাপ্লিকেশনটির প্রয়োজনীয় কোডগুলি বা পদ্ধতি পরিবর্তন করার প্রয়োজন ছাড়াই এই অ্যাপ্লিকেশনগুলিতে এই টেবিলগুলিতে ডেটা তৈরি করার অনুমতি দেওয়ার সময়ও অনেকগুলি অ্যাপ্লিকেশন জুড়ে সাধারণ তথ্যগুলির জন্য ডেটাবেস আপডেট করার সক্ষমতা প্রয়োজন।

সুতরাং মূলত, আমরা একটি কলাম সংজ্ঞা থেকে সরানো হয়েছে;

PkId INT IDENTITY(1,1) PRIMARY KEY

প্রতি;

PkId AS AS COALESCE(old_id, external_id, new_id) PERSISTED NOT NULL,
old_id INT NULL, -- Values here are from existing records of PkId before table change
external_id INT NULL,
new_id INT IDENTITY(2000000,1) NOT NULL

সমস্ত ক্ষেত্রে পিকেআইডি একটি প্রাথমিক কী এবং সমস্ত ক্ষেত্রে একটি ক্ষেত্রে, এটি ক্লাস্টার্ড। সমস্ত টেবিলের আগের মতো একই বিদেশী কী এবং সূচি রয়েছে। সংক্ষেপে, নতুন ফর্ম্যাটটি PkId কে ডিকپلড অ্যাপ্লিকেশন (বহিরাগত_আইডি হিসাবে) সরবরাহ করার অনুমতি দেয়, তবে পিকআইডিকে আইডেন্টিটি কলাম মান হতে দেয় সুতরাং বিদ্যমান কোড যা এসসিওপিডিআইডিএনটি এবং @@ পরিচয় ব্যবহারের মাধ্যমে আইডেন্টিটি কলামে নির্ভর করে allowing এটি ব্যবহৃত হিসাবে কাজ।

আমাদের যে সমস্যাটি হয়েছিল তা হ'ল আমরা বেশ কয়েকটি ক্যোয়ারী জুড়ে এসেছি যা গ্রহণযোগ্য সময়ে চালিত হয়ে এখন পুরোপুরি ফুটিয়ে উঠবে। এই ক্যোয়ারীগুলি ব্যবহার করে উত্পন্ন উত্পন্ন ক্যোয়ারী পরিকল্পনাগুলি আগের মতো কিছুই ছিল না।

নতুন কলামটি একটি প্রাথমিক কী দেওয়া হয়েছে, আগের মত একই ধরণের ডেটা টাইপ এবং পার্সট করা হয়েছে, আমি কোয়েরি এবং ক্যোয়ারীগুলি তাদের আগের মতো আচরণ করার প্রত্যাশা করতাম। এসকিউএল সার্ভার এক্সিকিউশন প্ল্যান কীভাবে উত্পাদিত করবে তার পরিপ্রেক্ষিতে এসএমএল সার্ভার কীভাবে স্পষ্টত আইএনটি সংজ্ঞা হিসাবে একইভাবে আচরণ করা উচিত? আপনি দেখতে পারেন যে এই পদ্ধতির সাথে অন্যান্য সম্ভাব্য সমস্যা আছে?

এই পরিবর্তনের উদ্দেশ্যটি আমাদের বিদ্যমান পদ্ধতি এবং কোডটি পরিবর্তন করার প্রয়োজন ছাড়াই সারণির সংজ্ঞা পরিবর্তন করার অনুমতি দেওয়ার কথা ছিল allow এই সমস্যাগুলি দেওয়া, আমি মনে করি না যে আমরা এই পদ্ধতির সাথে যেতে পারি।


মন্তব্যগুলি বর্ধিত আলোচনার জন্য নয়; এই কথোপকথন চ্যাটে সরানো হয়েছে ।
পল হোয়াইট 9

উত্তর:


4

প্রথম

: আপনি সম্ভবত সব তিনটি কলাম প্রয়োজন হবে না old_id, external_id, new_idnew_idকলাম, একটি হচ্ছে IDENTITY, প্রতিটি সারিতে একটি নতুন মান এমনকি যখন আপনি মধ্যে সন্নিবেশ থাকবে, external_id। কিন্তু, মধ্যে old_idএবং external_idসেই প্রায় কাছাকাছি পারস্পরিক একচেটিয়া: হয় সেখানে আগে থেকেই একটি old_idমান বা যে কলাম, বর্তমান ধারণা, যে হবে NULLযদি ব্যবহার external_idবা new_id। যেহেতু আপনি ইতিমধ্যে বিদ্যমান একটি সারিতে নতুন "বাহ্যিক" আইডি যুক্ত করবেন না (যেমন একটি old_idমান রয়েছে), এবং কোনও নতুন মান আসবে না old_id, তারপরে একটি কলাম ব্যবহার করা যেতে পারে উভয় উদ্দেশ্যে।

সুতরাং, external_idকলামটি থেকে মুক্তি পেয়ে নতুন নামকরণ old_idকরুন যা কিছু old_or_external_idবা যা কিছু হোক। এটির জন্য কোনও কিছুর আসল পরিবর্তনের প্রয়োজন হবে না, তবুও কিছু জটিলতা হ্রাস করতে পারে। external_idঅ্যাপ্লিকেশন কোডটি সন্নিবেশ করানোর জন্য ইতিমধ্যে লিখিত থাকলেও আপনাকে সম্ভবত কলামটি কল করতে হবে , যদিও এতে "পুরানো" মান রয়েছে external_id

এটি নতুন কাঠামোকে ন্যায়সঙ্গত হতে হ্রাস করে:

PkId AS AS COALESCE(old_or_external_id, new_id, -1) PERSISTED NOT NULL,
old_or_external_id INT NULL, -- values from existing record OR passed in from app
new_id INT IDENTITY(2000000, 1) NOT NULL

এখন আপনি 12 বাইটের পরিবর্তে সারি প্রতি 8 বাইট যুক্ত করেছেন (ধরে নিবেন যে আপনি SPARSEবিকল্প বা ডেটা সংক্ষেপণটি ব্যবহার করছেন না )। এবং আপনার কোনও কোড, টি-এসকিউএল বা অ্যাপ কোড পরিবর্তন করার দরকার নেই।

SECOND এ

সরলকরণের এই পথ অব্যাহত রেখে, আসুন আমরা কী রেখেছি তা দেখুন:

  • old_or_external_idকলাম হয় ইতোমধ্যে মান আছে, অথবা অ্যাপ্লিকেশন থেকে কোনো নতুন মান দেওয়া হবে, অথবা ছেড়ে দেওয়া হবে NULL
  • new_idসবসময় একটি নতুন মান থাকবে, কিন্তু যদি যে মান শুধুমাত্র ব্যবহার করা হবে old_or_external_idকলাম NULL

একটা সময় ছিল যখন আপনি উভয় মান হবে না হয় old_or_external_idএবং new_id। উভয় কলাম কারণে মান আছে হ্যাঁ, বার হতে হবে new_idএকটি হচ্ছে IDENTITY, কিন্তু সেসব new_idমান উপেক্ষা করা হয়। আবার এই দুটি ক্ষেত্র পারস্পরিক একচেটিয়া। এখন কি?

এখন আমরা কেন external_idপ্রথমে আমাদের প্রয়োজনের বিষয়টি খতিয়ে দেখতে পারি । এটি IDENTITYব্যবহার করে কলামে toোকানো সম্ভব তা বিবেচনা করে SET IDENTITY_INSERT {table_name} ON;আপনি কোনও স্কিমার কোনও পরিবর্তন না করেই পালিয়ে যেতে পারতেন এবং INSERTবিবৃতি / ক্রিয়াকলাপগুলিকে SET IDENTITY_INSERT {table_name} ON;এবং SET IDENTITY_INSERT {table_name} OFF;বিবৃতিগুলিকে মোড়ানোর জন্য কেবল আপনার অ্যাপ কোডটি সংশোধন করতে পারেন । তারপরে আপনাকে IDENTITYকলামটি পুনরায় সেট করার জন্য কোন প্রারম্ভিক ব্যাপ্তিটি নির্ধারণ করতে হবে (সদ্য উত্পন্ন মানগুলির জন্য) কারণ অ্যাপ্লিকেশন কোডটি যে মানগুলি সন্নিবেশ করানো হবে তার চেয়ে ভাল হওয়া দরকার যেহেতু একটি উচ্চতর মান সন্নিবেশ করানো পরের স্বয়ংক্রিয়ভাবে উত্পন্ন মানটির কারণ হবে বর্তমানের MAX মানের চেয়ে বড় হতে হবে। তবে আপনি সর্বদা IDENT_CURRENT মানের নীচে থাকা একটি মান সন্নিবেশ করতে পারেন ।

2 এবং এমনকি 3 এর অভিপ্রায় থেকে কলামগুলি old_or_external_idএবং new_idকলামগুলির সংমিশ্রণটি স্বতঃ উত্পাদিত মান এবং অ্যাপ্লিকেশন-উত্পাদিত মানগুলির মধ্যে ওভারল্যাপিং মান পরিস্থিতির দিকে পরিচালিত হওয়ার সম্ভাবনা বৃদ্ধি করে না, কলামগুলি তাদের একটি প্রাথমিক কী মানের সাথে একত্রিত করা, এবং সেগুলি সর্বদা অনন্য মান।

এই পদ্ধতির ক্ষেত্রে, আপনার কেবল দরকার:

  • হিসাবে টেবিলগুলি ছেড়ে দিন:

    PkId INT IDENTITY(1,1) PRIMARY KEY

    এটি 8 বা 12 এর পরিবর্তে প্রতিটি সারিতে 0 বাইট যুক্ত করে।

  • অ্যাপ্লিকেশন-উত্পাদিত মানগুলির জন্য প্রারম্ভিক ব্যাপ্তি নির্ধারণ করুন। এগুলি প্রতিটি টেবিলের বর্তমান MAX মানের চেয়ে বেশি হবে তবে স্বয়ংক্রিয়ভাবে উত্পন্ন মানগুলির জন্য সর্বনিম্ন মান হয়ে উঠবে তার চেয়ে কম।
  • স্বতঃ উত্পাদিত পরিসীমাটি কী থেকে শুরু হওয়া উচিত তা নির্ধারণ করুন। বর্তমানের ম্যাক্স মান এবং বাড়ার জন্য প্রচুর কক্ষের মধ্যে প্রচুর জায়গা থাকতে হবে, উপরের সীমাতে জেনে মাত্র ২.১৪ বিলিয়ন over তারপরে আপনি এই নতুন সর্বনিম্ন বীজ মানটি ডিবিসিসি চেকিডেন্টের মাধ্যমে নির্ধারণ করতে পারেন ।
  • অ্যাপ কোড INSERT গুলি SET IDENTITY_INSERT {table_name} ON;এবং SET IDENTITY_INSERT {table_name} OFF;বিবৃতি মোড়ানো W

দ্বিতীয়, খণ্ড বি

উপরে উল্লিখিত পদ্ধতির পরিবর্তনে হ'ল অ্যাপ কোড সন্নিবেশ মানগুলি -1 দিয়ে শুরু হবে এবং সেখান থেকে নীচে নামবে । এর ফলে IDENTITYমানগুলি কেবলমাত্র উপরে চলে যায় । এখানে সুবিধাটি হ'ল আপনি কেবল স্কিমাটিকে জটিল করবেন না, আপনাকে ওভারল্যাপিং আইডিগুলিতে চলার বিষয়েও চিন্তা করার দরকার নেই (যদি অ্যাপ্লিকেশন-উত্পন্ন মানগুলি নতুন স্বয়ংক্রিয়ভাবে উত্পাদিত পরিসীমাতে চালিত হয়)। এটি কেবলমাত্র একটি বিকল্প যদি আপনি ইতিমধ্যে নেতিবাচক আইডি মান ব্যবহার করছেন না (এবং এটি স্বয়ংক্রিয়ভাবে উত্পন্ন কলামগুলিতে নেতিবাচক মান ব্যবহার করা খুব বিরল বলে মনে হয় তাই বেশিরভাগ পরিস্থিতিতে এটি সম্ভবত সম্ভাবনাময় হওয়া উচিত)।

এই পদ্ধতির ক্ষেত্রে, আপনার কেবল দরকার:

  • হিসাবে টেবিলগুলি ছেড়ে দিন:

    PkId INT IDENTITY(1,1) PRIMARY KEY

    এটি 8 বা 12 এর পরিবর্তে প্রতিটি সারিতে 0 বাইট যুক্ত করে।

  • অ্যাপ্লিকেশন-উত্পাদিত মানগুলির জন্য প্রারম্ভিক ব্যাপ্তি হবে -1
  • অ্যাপ কোড INSERT গুলি SET IDENTITY_INSERT {table_name} ON;এবং SET IDENTITY_INSERT {table_name} OFF;বিবৃতি মোড়ানো W

এখানে আপনার এখনও করতে হবে IDENTITY_INSERT, তবে: আপনি কোনও নতুন কলাম যুক্ত করবেন না IDENTITY, কোনও কলামকে "পুনরায় গবেষণা" করতে হবে না এবং ভবিষ্যতে ওভারল্যাপের ঝুঁকি নেই।

দ্বিতীয়, অংশ 3

এই পদ্ধতির একটি সর্বশেষ প্রকরণটি সম্ভবত IDENTITYকলামগুলি সরিয়ে আনা এবং তার পরিবর্তে সিকোয়েন্সগুলি ব্যবহার করা হবে । এই পদ্ধতির গ্রহণের কারণটি হ'ল অ্যাপ কোডটি সন্নিবেশ করা মানগুলি সক্ষম করতে সক্ষম হবেন: ইতিবাচক, স্বতঃ উত্পাদিত পরিসরের উপরে (নীচে নয়) এবং প্রয়োজন নেই SET IDENTITY_INSERT ON / OFF

এই পদ্ধতির ক্ষেত্রে, আপনার কেবল দরকার:

  • ক্রিয়েট সিকোয়েন্স ব্যবহার করে সিকোয়েন্স তৈরি করুন
  • IDENTITYনতুন কলামে কলামটি অনুলিপি করুন যেখানে IDENTITYসম্পত্তি নেই, তবে ফাংশনটির জন্য নেক্সটDEFAULT ভ্যালু ব্যবহার করে কোনও সীমাবদ্ধতা রয়েছে :

    PkId INT PRIMARY KEY CONSTRAINT [DF_TableName_NextID] DEFAULT (NEXT VALUE FOR...)

    এটি 8 বা 12 এর পরিবর্তে প্রতিটি সারিতে 0 বাইট যুক্ত করে।

  • অ্যাপ্লিকেশন-উত্পাদিত মানগুলির জন্য প্রারম্ভিক ব্যাপ্তি স্বয়ংক্রিয়ভাবে উত্পন্ন মূল্যবোধগুলির কাছাকাছি আসবে বলে আপনি ঠিক তার উপরে চলে যাবেন।
  • অ্যাপ কোড INSERT গুলি SET IDENTITY_INSERT {table_name} ON;এবং SET IDENTITY_INSERT {table_name} OFF;বিবৃতি মোড়ানো W

তা যে , প্রয়োজন যে হয় সঙ্গে কোডের কারণে SCOPE_IDENTITY()বা @@IDENTITYএখনও ফাংশন সঠিকভাবে, সিকোয়েন্স স্যুইচ বর্তমানে একটি বিকল্প হিসাবে দেখা সিকোয়েন্স জন্য :-( যারা ফাংশন কোন সমতূল্য যে নেই। দুঃখি!


আপনার উত্তরের জন্য অনেক ধন্যবাদ। আপনি অভ্যন্তরীণভাবে এখানে কয়েকটি পয়েন্ট উত্থাপন করেছিলেন raise দুর্ভাগ্যক্রমে, এর কয়েকটি বেশ কয়েকটি কারণে আমাদের পক্ষে কাজ করবে না। আমাদের ডাটাবেসটি বেশ পুরানো এবং কিছুটা ভঙ্গুর এবং 2005 এর সামঞ্জস্য মোডের অধীনে চলেছে তাই সিক্যুয়েন্সগুলি বাইরে। আমাদের অ্যাপ্লিকেশন ডেটা পুশ এমন ডেটা লোড সরঞ্জামের মাধ্যমে ঘটে যা পরিষেবা ব্রোকার সারিগুলি থেকে নতুন রেকর্ডগুলি গ্রহণ করে এবং একাধিক থ্রেডের মাধ্যমে তাদের ধাক্কা দেয়। পরিচয়পত্রের নামটি প্রতি সেশনের জন্য কেবল একটি টেবিলের জন্য ব্যবহার করা যেতে পারে এবং বর্তমান চিন্তাভাবনাটি আমাদের আর্কিটেকচারটি উল্লেখযোগ্য পরিবর্তন ছাড়াই এটি পূরণ করতে পারে না। আমি আপনার মুষ্টি পরামর্শ এখন পরীক্ষা করছি।
মিঃ মোজেব

@ শ্রীমূস হ্যাঁ, আমি শেষে উত্তরগুলি সম্পর্কে আরও তথ্য অন্তর্ভুক্ত করার জন্য আমার উত্তর আপডেট করেছি। এটি যাইহোক আপনার পরিস্থিতিতে কাজ করবে না। এবং আমি সম্ভাব্য সম্মতি সংক্রান্ত সমস্যাগুলি নিয়ে ভাবছিলাম IDENTITY_INSERT, তবে এটি পরীক্ষা করিনি । নিশ্চিত নয় যে বিকল্প # 1 আপনার সামগ্রিক সমস্যার সমাধান করতে চলেছে, এটি অযথা জটিলতা হ্রাস করার জন্য কেবল একটি পর্যবেক্ষণ ছিল। তবুও, যদি আপনার কাছে নতুন "বাহ্যিক" আইডি ?োকানো একাধিক থ্রেড থাকে তবে কীভাবে আপনি গ্যারান্টি দিবেন যে সেগুলি অনন্য?
সলোমন রুটজকি

@ মিঃমূজ প্রকৃতপক্ষে, " আইডেন্টিটিআইপিএসইআরটি শুধুমাত্র প্রতি সেশনের জন্য একটি টেবিলের জন্য ব্যবহার করা যেতে পারে " সম্পর্কিত, এখানে সমস্যাটি আসলে কী? 1) আপনি একবারে কেবল একটি টেবিলের মধ্যে সন্নিবেশ করতে পারেন, সুতরাং আপনি টেবিলবিতে beforeোকানোর আগে এটি টেবিলএর জন্য বন্ধ করে দিয়েছেন, এবং ২) আমি যা যা ভেবে দেখেছিলাম তার বিপরীতে আমি পরীক্ষা করেছি এবং এর সাথে কোনও মিল নেই - আমি সক্ষম হয়েছি আছে IDENTITY_INSERT ONদুটি সেশন একই টেবিল এবং কোন সমস্যার সঙ্গে উভয় মধ্যে ঢোকাতে হয়।
সলোমন রুটজকি

1
আপনি যেমন পরামর্শ দিয়েছেন, পরিবর্তন 1 এর ফলে কিছুটা পার্থক্য হয়েছে। আমরা যে আইডিটি ব্যবহার করব তা বর্তমান ডাটাবেসের বাইরে বরাদ্দ করা হবে এবং রেকর্ডগুলি সম্পর্কিত করতে ব্যবহৃত হবে। এটি ভাল হতে পারে যে আমার সেশনগুলির বোঝাপড়াটি ঠিক ঠিক নয় তাই আইডেন্টিটিআইপিএসআরটি কাজ করতে পারে। যদিও এটি তদন্ত করতে আমার একটু সময় লাগবে, তাই আমি কিছুক্ষণের জন্য ফিরে রিপোর্ট করতে পারব না। ইনপুট জন্য আবার ধন্যবাদ। এটা অনেক প্রশংসা করা হয়।
মিঃ মোজেব

1
আমি মনে করি আইডিএনটিআইটিএসইআরটি (বিদ্যমান অ্যাপ্লিকেশনগুলির জন্য উচ্চ বীজের মান সহ) ব্যবহারের আপনার পরামর্শটি কার্যকরভাবে কাজ করবে। অ্যারন বারট্রান্ড এখানে একত্রীকরণের সাথে পরীক্ষার জন্য একটি ভাল ছোট উদাহরণ সহ একটি উত্তর সরবরাহ করেছে । আমরা পরিচয় মান নির্দিষ্ট করতে হবে এমন টেবিলগুলি পরিচালনা করতে সক্ষম হওয়ার জন্য আমরা আমাদের ডেটা লোড সরঞ্জামটি পরিবর্তন করেছি এবং আমরা আগামী সপ্তাহগুলিতে আরও কিছু পরীক্ষা নেব।
মিঃ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.