เป็นประเภทที่ไม่ถูกต้องสำหรับใช้เป็นคอลัมน์สำคัญในดัชนี


180

ฉันมีข้อผิดพลาดที่

Column 'key' in table 'misc_info' is of a type that is invalid for use as a key column in an index.

โดยที่ key คือ nvarchar (สูงสุด) ของ Google อย่างรวดเร็วพบนี้ อย่างไรก็ตามมันไม่ได้อธิบายว่าทางออกคืออะไร ฉันจะสร้างบางสิ่งเช่นพจนานุกรมโดยที่คีย์และค่าเป็นทั้งสตริงและเห็นได้ชัดว่าคีย์ต้องไม่ซ้ำกันและเป็นแบบเดี่ยว คำสั่ง SQL ของฉันคือ

create table [misc_info] (
[id] INTEGER PRIMARY KEY IDENTITY NOT NULL,
[key] nvarchar(max) UNIQUE NOT NULL,
[value] nvarchar(max) NOT NULL);

16
คุณต้องการกุญแจของคุณให้มีขนาดใหญ่และไม่เหมือนใคร 4GB SqlServer ไม่อนุญาตให้มีการตรวจสอบนี้เพราะเอกลักษณ์ที่อาจเกิดขึ้นอาจจะเป็นมากการดำเนินงานที่ใช้เวลานาน
Klaus Byskov Pedersen

@ KlausByskovPedersen บาง DBMS ที่มีประสิทธิภาพมากขึ้นเช่น PostgreSQL นั้นฉลาดพอที่จะอนุญาตและสร้างดัชนีย่อยแทน แต่คุณมีประเด็น
Matthieu

คำตอบ:


244

ข้อ จำกัด ที่ไม่ซ้ำกันต้องไม่เกิน 8000 ไบต์ต่อแถวและจะใช้เพียง 900 ไบต์แรกเท่านั้นดังนั้นขนาดสูงสุดที่ปลอดภัยที่สุดสำหรับคีย์ของคุณคือ:

create table [misc_info]
( 
    [id] INTEGER PRIMARY KEY IDENTITY NOT NULL, 
    [key] nvarchar(450) UNIQUE NOT NULL, 
    [value] nvarchar(max) NOT NULL
)

นั่นคือกุญแจสำคัญต้องมีความยาวไม่เกิน 450 อักขระ หากคุณสามารถเปลี่ยนไปvarcharใช้แทนnvarchar(เช่นหากคุณไม่ต้องการจัดเก็บอักขระจากเพจเพจมากกว่าหนึ่งเพจ) นั่นอาจเพิ่มเป็น 900 อักขระได้


1
สำหรับ varchar ขีด จำกัด จะยังคงเป็น varchar (450)
Steam

9
คุณมีพื้นที่ที่จะใช้อย่างใดอย่างหนึ่งหรือvarchar(900) nvarchar(450)
Daniel Renshaw

ความเข้าใจของฉันคือ varchar จะใช้เวลา 4 ไบต์เพื่อกำหนดความยาวของรายการหมายถึงขีด จำกัด ที่แท้จริงจะต้องเป็น varchar (896) ถูกต้องหรือไม่
mrmillsy

2
@mrmillsy ขนาดสูงสุดที่ประกาศไม่รวมค่าโสหุ้ย (ซึ่งคือ 2 ไบต์ไม่ใช่ 4) และไบต์ค่าใช้จ่ายจะไม่รวมอยู่ในขีด จำกัด ของขนาดแถวดัชนีสูงสุด technet.microsoft.com/en-us/library/ms176089(v=sql.100).aspx
Daniel Renshaw

1
@mrmillsy คุณได้รับข้อความนั้นเพราะคุณรวมID1 intอยู่ในดัชนี ที่intต้องใช้ 4 ไบต์นอกเหนือไปจาก 900 varcharไบต์สำหรับ
Daniel Renshaw

33

มีข้อ จำกัด ใน SQL Server (จนถึง 2008 R2) ที่ varchar (MAX) และ nvarchar (MAX) (และประเภทอื่น ๆ เช่น text, ntext) ไม่สามารถใช้ในดัชนีได้ คุณมี 2 ตัวเลือก:
1. ตั้งค่าขนาดที่ จำกัด บนฟิลด์คีย์เช่น nvarchar (100)
2. สร้างข้อ จำกัด การตรวจสอบที่เปรียบเทียบค่ากับคีย์ทั้งหมดในตาราง เงื่อนไขคือ:

([dbo].[CheckKey]([key])=(1))

และ [dbo] [CheckKey] เป็นฟังก์ชันสเกลาร์ที่กำหนดเป็น:

CREATE FUNCTION [dbo].[CheckKey]
(
    @key nvarchar(max)
)
RETURNS bit
AS
BEGIN
    declare @res bit
    if exists(select * from key_value where [key] = @key)
        set @res = 0
    else
        set @res = 1

    return @res
END

แต่โปรดทราบว่าดัชนีเนทิฟนั้นมีประสิทธิภาพมากกว่าข้อ จำกัด การตรวจสอบดังนั้นหากคุณไม่สามารถระบุความยาวได้อย่าใช้ข้อ จำกัด การตรวจสอบ


ฉันฉลาดกว่าดีกว่าทริกเกอร์
Neil Moss

14

ทางออกเดียวคือการใช้ข้อมูลน้อยลงในดัชนีที่ไม่ซ้ำของคุณ คีย์ของคุณสามารถเป็น NVARCHAR (450) ได้มากที่สุด

"SQL Server ยังคงขีด จำกัด 900 ไบต์สำหรับขนาดรวมสูงสุดของคอลัมน์คีย์ดัชนีทั้งหมด"

อ่านเพิ่มเติมที่MSDN


สำหรับ varchar ขีด จำกัด จะยังคงเป็น varchar (450)
Steam


2

สังเกตความคิดเห็นของ klaisbyskov เกี่ยวกับความยาวกุญแจของคุณจำเป็นต้องมีขนาดกิกะไบต์และสมมติว่าคุณจำเป็นต้องใช้ความจริงแล้วฉันคิดว่าทางเลือกเดียวของคุณคือ:

  1. ใช้แฮชของค่าคีย์
    • สร้างคอลัมน์ใน nchar (40) (สำหรับแฮช sha1 เป็นต้น)
    • ใส่รหัสเฉพาะในคอลัมน์แฮช
    • สร้างแฮชเมื่อบันทึกหรืออัพเดตเรกคอร์ด
  2. ทริกเกอร์เพื่อสอบถามตารางสำหรับการแข่งขันที่มีอยู่ในการแทรกหรือปรับปรุง

Hashing มาพร้อมกับข้อแม้ที่วันหนึ่งคุณอาจได้รับการปะทะกัน

ทริกเกอร์จะสแกนทั้งตาราง

ไปยังคุณ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.